X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fwgtpkg-unit.c;h=3f2095c3ede454959819e5bec8c69972e78453db;hb=17f9cdadca63005fe075d999e49154342fdd5086;hp=93cfe6402d9db143cf5afd25541128de80708828;hpb=de02ff4734caf96658f40a9e352245f5046a183a;p=src%2Fapp-framework-main.git diff --git a/src/wgtpkg-unit.c b/src/wgtpkg-unit.c index 93cfe64..3f2095c 100644 --- a/src/wgtpkg-unit.c +++ b/src/wgtpkg-unit.c @@ -35,13 +35,10 @@ #include "wgtpkg-mustach.h" #include "utils-json.h" #include "wgt-json.h" +#include "utils-systemd.h" #include "wgtpkg-unit.h" -#if !defined(SYSTEMD_UNITS_ROOT) -# define SYSTEMD_UNITS_ROOT "/usr/local/lib/systemd" -#endif - #if 0 #include #else @@ -119,12 +116,13 @@ static size_t pack(char *text, char purge) char cont; /* flag telling whether the line continues the previous one */ char nextcont; /* flag telling whether the line will continues the next one */ - cont = 0; + nextcont = 0; c = *(write = read = text); /* iteration over lines */ while (c) { /* computes emit, nextcont, emit and start for the current line */ + cont = nextcont; emit = nextcont = 0; start = NULL; begin = read; @@ -143,7 +141,7 @@ static size_t pack(char *text, char purge) if (c) c = *++read; /* emit the line if not empty */ - if (emit) { + if (emit || (cont && !nextcont)) { /* removes the blanks on the left of not continuing lines */ if (!cont && start) begin = start; @@ -158,7 +156,6 @@ static size_t pack(char *text, char purge) *write++ = *begin++; } } - cont = nextcont; } *write = 0; return (size_t)(write - text); @@ -193,8 +190,8 @@ static char *offset(char *text, const char *pattern, char **args) */ static int process_one_unit(char *spec, struct unitdesc *desc) { - char *nsoc, *nsrv, *name; - int isuser, issystem, issock, isserv; + char *nsoc, *nsrv, *name, *wanted; + int isuser, issystem, issock, isserv, iswanted; size_t len; /* finds the configuration directive of the unit */ @@ -202,6 +199,7 @@ static int process_one_unit(char *spec, struct unitdesc *desc) issystem = !!offset(spec, "%systemd-unit system\n", NULL); issock = !!offset(spec, "%systemd-unit socket ", &nsoc); isserv = !!offset(spec, "%systemd-unit service ", &nsrv); + iswanted = !!offset(spec, "%systemd-unit wanted-by ", &wanted); /* check the unit scope */ if ((isuser + issystem) == 1) { @@ -228,6 +226,15 @@ static int process_one_unit(char *spec, struct unitdesc *desc) desc->name_length = 0; } + if (iswanted) { + len = (size_t)(strchrnul(wanted, '\n') - wanted); + desc->wanted_by = strndup(wanted, len); + desc->wanted_by_length = len; + } else { + desc->wanted_by = NULL; + desc->wanted_by_length = 0; + } + desc->content = spec; desc->content_length = pack(spec, '%'); @@ -242,14 +249,14 @@ static int process_one_unit(char *spec, struct unitdesc *desc) * with its given 'closure' and the array descripbing the units. * Return 0 in case of success or a negative value in case of error. */ -static int process_all_units(char *corpus, int (*process)(void *closure, const struct unitdesc descs[], unsigned count), void *closure) +static int process_all_units(char *corpus, const struct unitconf *conf, int (*process)(void *closure, const struct generatedesc *desc), void *closure) { - int rc, rc2; - unsigned n; + int n, rc, rc2; char *beg, *end; - struct unitdesc *descs, *d; + struct unitdesc *units, *u; + struct generatedesc gdesc; - descs = NULL; + units = NULL; n = 0; rc = rc2 = 0; @@ -268,14 +275,15 @@ static int process_all_units(char *corpus, int (*process)(void *closure, const s *end = 0; /* allocates a descriptor for the unit */ - d = realloc(descs, (n + 1) * sizeof *descs); - if (d == NULL) + u = realloc(units, ((unsigned)n + 1) * sizeof *units); + if (u == NULL) rc2 = -ENOMEM; else { /* creates the unit description */ - memset(&d[n], 0, sizeof *d); - descs = d; - rc2 = process_one_unit(beg, &descs[n]); + units = u; + u = &u[n]; + memset(u, 0, sizeof *u); + rc2 = process_one_unit(beg, u); if (rc2 >= 0) n++; } @@ -288,13 +296,19 @@ static int process_all_units(char *corpus, int (*process)(void *closure, const s } /* call the function that processes the units */ - if (rc == 0 && process) - rc = process(closure, descs, n); + if (rc == 0 && process) { + gdesc.conf = conf; + gdesc.units = units; + gdesc.nunits = n; + rc = process(closure, &gdesc); + } /* cleanup and frees */ - while(n) - free((char *)(descs[--n].name)); - free(descs); + while(n) { + free((char *)(units[--n].name)); + free((char *)(units[n].wanted_by)); + } + free(units); return rc; } @@ -329,8 +343,22 @@ int unit_generator_on(const char *filename) return rc; } +static int add_metadata(struct json_object *jdesc, const struct unitconf *conf) +{ + char portstr[30]; + + sprintf(portstr, "%d", conf->port); + return j_add_many_strings_m(jdesc, + "#metadata.install-dir", conf->installdir, + "#metadata.app-data-dir", "%h/app-data", + "#metadata.icons-dir", conf->icondir, + "#metadata.http-port", portstr, + NULL) ? 0 : -1; +} + /* - * Applies the object 'jdesc' to the current unit generator. + * Applies the object 'jdesc' augmented of meta data coming + * from 'conf' to the current unit generator. * The current unit generator will be set to the default one if not unit * was previously set using the function 'unit_generator_on'. * The callback function 'process' is then called with the @@ -338,105 +366,192 @@ int unit_generator_on(const char *filename) * Return what returned process in case of success or a negative * error code. */ -int unit_generator_process(struct json_object *jdesc, int (*process)(void *closure, const struct unitdesc descs[], unsigned count), void *closure) +int unit_generator_process(struct json_object *jdesc, const struct unitconf *conf, int (*process)(void *closure, const struct generatedesc *desc), void *closure) { int rc; size_t size; char *instance; - rc = template ? 0 : unit_generator_on(NULL); - if (!rc) { - instance = NULL; - rc = apply_mustach(template, jdesc, &instance, &size); - if (!rc) - rc = process_all_units(instance, process, closure); - free(instance); + rc = add_metadata(jdesc, conf); + if (rc) + ERROR("can't set the metadata. %m"); + else { + rc = template ? 0 : unit_generator_on(NULL); + if (!rc) { + instance = NULL; + rc = apply_mustach(template, jdesc, &instance, &size); + if (!rc) + rc = process_all_units(instance, conf, process, closure); + free(instance); + } } return rc; } /**************** SPECIALIZED PART *****************************/ - -static int get_unit_path(char *path, size_t pathlen, const struct unitdesc *desc) +static int check_unit_desc(const struct unitdesc *desc, int tells) { - int rc; + if (desc->scope != unitscope_unknown && desc->type != unittype_unknown && desc->name != NULL) + return 0; - if (desc->scope == unitscope_unknown || desc->type == unittype_unknown || desc->name == NULL) { + if (tells) { if (desc->scope == unitscope_unknown) ERROR("unit of unknown scope"); if (desc->type == unittype_unknown) ERROR("unit of unknown type"); if (desc->name == NULL) ERROR("unit of unknown name"); - errno = EINVAL; - rc = -1; - } - else { - rc = snprintf(path, pathlen, "%s/%s/%s.%s", - SYSTEMD_UNITS_ROOT, - desc->scope == unitscope_system ? "system" : "user", - desc->name, - desc->type == unittype_socket ? "socket" : "service"); - - if (rc >= 0 && (size_t)rc >= pathlen) { - ERROR("can't set the unit name"); - errno = EINVAL; - rc = -1; - } } + errno = EINVAL; + return -1; +} + +static int get_unit_path(char *path, size_t pathlen, const struct unitdesc *desc) +{ + int rc = systemd_get_unit_path( + path, pathlen, desc->scope == unitscope_user, + desc->name, desc->type == unittype_socket ? "socket" : "service"); + + if (rc < 0) + ERROR("can't get the unit path for %s", desc->name); + return rc; } -static int do_install_units(void *closure, const struct unitdesc descs[], unsigned count) +static int get_wants_path(char *path, size_t pathlen, const struct unitdesc *desc) { - int rc; - unsigned i; - char path[PATH_MAX + 1]; + int rc = systemd_get_wants_path( + path, pathlen, desc->scope == unitscope_user, desc->wanted_by, + desc->name, desc->type == unittype_socket ? "socket" : "service"); - for (i = 0 ; i < count ; i++) { - rc = get_unit_path(path, sizeof path, &descs[i]); - if (rc >= 0) { - rc = putfile(path, descs[i].content, descs[i].content_length); + if (rc < 0) + ERROR("can't get the wants path for %s and %s", desc->name, desc->wanted_by); + + return rc; +} + +static int get_wants_target(char *path, size_t pathlen, const struct unitdesc *desc) +{ + int rc = systemd_get_wants_target( + path, pathlen, + desc->name, desc->type == unittype_socket ? "socket" : "service"); + + if (rc < 0) + ERROR("can't get the wants target for %s", desc->name); + + return rc; +} + +static int do_send_reload(const struct generatedesc *desc) +{ + int i; + int reloadsys, reloadusr; + const struct unitdesc *u; + + reloadsys = reloadusr = 0; + for (i = 0 ; i < desc->nunits ; i++) { + u = &desc->units[i]; + if (u->wanted_by != NULL) { + switch (u->scope) { + case unitscope_user: + reloadusr = 1; + break; + case unitscope_system: + reloadsys = 1; + break; + default: + break; + } } } - return 0; + + if (reloadusr) + reloadusr = systemd_daemon_reload(1); + if (reloadsys) + reloadsys = systemd_daemon_reload(0); + return reloadsys ? : reloadusr ? : 0; } -static int do_uninstall_units(void *closure, const struct unitdesc descs[], unsigned count) +static int do_uninstall_units(void *closure, const struct generatedesc *desc) { - int rc; - unsigned i; + int rc, rc2; + int i; char path[PATH_MAX]; - - for (i = 0 ; i < count ; i++) { - rc = get_unit_path(path, sizeof path, &descs[i]); - if (rc >= 0) { - rc = unlink(path); + const struct unitdesc *u; + + rc = 0; + for (i = 0 ; i < desc->nunits ; i++) { + u = &desc->units[i]; + rc2 = check_unit_desc(u, 0); + if (rc2 == 0) { + rc2 = get_unit_path(path, sizeof path, u); + if (rc2 >= 0) { + rc2 = unlink(path); + } + if (rc2 < 0 && rc == 0) + rc = rc2; + if (u->wanted_by != NULL) { + rc2 = get_wants_path(path, sizeof path, u); + if (rc2 >= 0) + rc2 = unlink(path); + } } + if (rc2 < 0 && rc == 0) + rc = rc2; } - return 0; + rc2 = do_send_reload(desc); + if (rc2 < 0 && rc == 0) + rc = rc2; + return rc; } -static int add_metadata(struct json_object *jdesc, const char *installdir, const char *icondir, int port) +static int do_install_units(void *closure, const struct generatedesc *desc) { - char portstr[30]; - - sprintf(portstr, "%d", port); - return j_add_many_strings_m(jdesc, - "#metadata.install-dir", installdir, - "#metadata.app-data-dir", "%h/app-data", - "#metadata.icons-dir", icondir, - "#metadata.http-port", portstr, - NULL) ? 0 : -1; + int rc; + int i; + char path[PATH_MAX + 1], target[PATH_MAX + 1]; + const struct unitdesc *u; + + i = 0; + while (i < desc->nunits) { + u = &desc->units[i]; + rc = check_unit_desc(u, 1); + if (!rc) { + rc = get_unit_path(path, sizeof path, u); + if (rc >= 0) { + rc = putfile(path, u->content, u->content_length); + if (rc >= 0 && u->wanted_by != NULL) { + rc = get_wants_path(path, sizeof path, u); + if (rc >= 0) { + rc = get_wants_target(target, sizeof target, u); + if (rc >= 0) { + unlink(path); /* TODO? check? */ + rc = symlink(target, path); + } + } + } + i++; + } + } + if (rc < 0) + goto error; + } + rc = do_send_reload(desc); + if (rc < 0) + goto error; + return 0; +error: + i = errno; + do_uninstall_units(closure, desc); + errno = i; + return rc; } static int do_install_uninstall( struct wgt_info *ifo, - const char *installdir, - const char *icondir, - int port, - int (*doer)(void *, const struct unitdesc[], unsigned) + const struct unitconf *conf, + int (*doer)(void *, const struct generatedesc *) ) { int rc; @@ -446,26 +561,19 @@ static int do_install_uninstall( if (!jdesc) rc = -1; else { - rc = add_metadata(jdesc, installdir, icondir, port); - if (rc) - ERROR("can't set the metadata. %m"); - else { - rc = unit_generator_process(jdesc, doer, NULL); - if (rc) - ERROR("can't install units, error %d", rc); - } + rc = unit_generator_process(jdesc, conf, doer, NULL); json_object_put(jdesc); } return rc; } -int unit_install(struct wgt_info *ifo, const char *installdir, const char *icondir, int port) +int unit_install(struct wgt_info *ifo, const struct unitconf *conf) { - return do_install_uninstall(ifo, installdir, icondir, port, do_install_units); + return do_install_uninstall(ifo, conf, do_install_units); } -int unit_uninstall(struct wgt_info *ifo) +int unit_uninstall(struct wgt_info *ifo, const struct unitconf *conf) { - return do_install_uninstall(ifo, "", "", 0, do_uninstall_units); + return do_install_uninstall(ifo, conf, do_uninstall_units); }