X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fwgtpkg-unit.c;h=9e6a1e23ac57049b63c24a546c018f88679733f2;hb=cdd05aa3e66a876dba01f04173d817b9e5e039a0;hp=26cf324571c19db9bbacfde054bed517402a85dd;hpb=14d4c3fe7e351c12f1cc4ec6246a23ae94dca7da;p=src%2Fapp-framework-main.git diff --git a/src/wgtpkg-unit.c b/src/wgtpkg-unit.c index 26cf324..9e6a1e2 100644 --- a/src/wgtpkg-unit.c +++ b/src/wgtpkg-unit.c @@ -25,13 +25,23 @@ #include #include #include +#include + +#include #include "verbose.h" #include "utils-file.h" #include "wgtpkg-mustach.h" +#include "utils-json.h" +#include "wgt-json.h" + #include "wgtpkg-unit.h" +#if !defined(SYSTEMD_UNITS_ROOT) +# define SYSTEMD_UNITS_ROOT "/usr/local/lib/systemd" +#endif + #if 0 #include #else @@ -183,8 +193,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 */ @@ -192,6 +202,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) { @@ -218,6 +229,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, '%'); @@ -282,8 +302,10 @@ static int process_all_units(char *corpus, int (*process)(void *closure, const s rc = process(closure, descs, n); /* cleanup and frees */ - while(n) + while(n) { free((char *)(descs[--n].name)); + free((char *)(descs[n].wanted_by)); + } free(descs); return rc; @@ -299,7 +321,7 @@ void unit_generator_off() } /* - * Initialises the unit generator with 'filename'. + * Initialises the unit generator with the content of the file of path 'filename'. * Returns 0 in case of success or a negative number in case of error. */ int unit_generator_on(const char *filename) @@ -345,3 +367,184 @@ int unit_generator_process(struct json_object *jdesc, int (*process)(void *closu return rc; } +/**************** SPECIALIZED PART *****************************/ + +static int check_unit_desc(const struct unitdesc *desc, int tells) +{ + if (desc->scope != unitscope_unknown && desc->type != unittype_unknown && desc->name != NULL) + return 0; + + 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; + return -1; +} + +static int get_unit_path(char *path, size_t pathlen, const struct unitdesc *desc) +{ + int rc; + + 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 path"); + errno = EINVAL; + rc = -1; + } + return rc; +} + +static int get_wants_path(char *path, size_t pathlen, const struct unitdesc *desc) +{ + int rc; + + rc = snprintf(path, pathlen, "%s/%s/%s.wants/%s.%s", + SYSTEMD_UNITS_ROOT, + desc->scope == unitscope_system ? "system" : "user", + desc->wanted_by, + desc->name, + desc->type == unittype_socket ? "socket" : "service"); + + if (rc >= 0 && (size_t)rc >= pathlen) { + ERROR("can't set the wants path"); + errno = EINVAL; + rc = -1; + } + return rc; +} + +static int get_wants_target(char *path, size_t pathlen, const struct unitdesc *desc) +{ + int rc; + + rc = snprintf(path, pathlen, "../%s.%s", + desc->name, + desc->type == unittype_socket ? "socket" : "service"); + + if (rc >= 0 && (size_t)rc >= pathlen) { + ERROR("can't set the wants target"); + errno = EINVAL; + rc = -1; + } + return rc; +} + +static int do_uninstall_units(void *closure, const struct unitdesc descs[], unsigned count) +{ + int rc, rc2; + unsigned i; + char path[PATH_MAX]; + + for (i = 0 ; i < count ; i++) { + rc = check_unit_desc(&descs[i], 0); + if (rc == 0) { + rc = get_unit_path(path, sizeof path, &descs[i]); + if (rc >= 0) { + rc = unlink(path); + } + if (descs[i].wanted_by != NULL) { + rc2 = get_wants_path(path, sizeof path, &descs[i]); + if (rc2 >= 0) + rc2 = unlink(path); + rc = rc < 0 ? rc : rc2; + } + } + } + return 0; +} + +static int do_install_units(void *closure, const struct unitdesc descs[], unsigned count) +{ + int rc; + unsigned i; + char path[PATH_MAX + 1], target[PATH_MAX + 1]; + + i = 0; + while (i < count) { + rc = check_unit_desc(&descs[i], 1); + if (!rc) { + rc = get_unit_path(path, sizeof path, &descs[i]); + if (rc >= 0) { + rc = putfile(path, descs[i].content, descs[i].content_length); + if (descs[i].wanted_by != NULL) { + rc = get_wants_path(path, sizeof path, &descs[i]); + if (rc >= 0) { + rc = get_wants_target(target, sizeof target, &descs[i]); + if (rc >= 0) { + unlink(path); /* TODO? check? */ + rc = symlink(target, path); + } + } + } + i++; + } + } + if (rc < 0) { + do_uninstall_units(closure, descs, i); + return rc; + } + } + return 0; +} + +static int add_metadata(struct json_object *jdesc, const char *installdir, const char *icondir, int port) +{ + 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; +} + +static int do_install_uninstall( + struct wgt_info *ifo, + const char *installdir, + const char *icondir, + int port, + int (*doer)(void *, const struct unitdesc[], unsigned) +) +{ + int rc; + struct json_object *jdesc; + + jdesc = wgt_info_to_json(ifo); + 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); + } + json_object_put(jdesc); + } + return rc; +} + +int unit_install(struct wgt_info *ifo, const char *installdir, const char *icondir, int port) +{ + return do_install_uninstall(ifo, installdir, icondir, port, do_install_units); +} + +int unit_uninstall(struct wgt_info *ifo) +{ + return do_install_uninstall(ifo, "", "", 0, do_uninstall_units); +} +