X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fwgtpkg-unit.c;h=e01faa9116f3fe505da716b856a2922c1e453bde;hb=6008a3ec4d1c0ed5df338b7c5f0775585ab51cfb;hp=48cf3bb295de846d33fdd92ad54b53bb94db474a;hpb=fb0f81a1d8b5369842269fa1bdb9ad8d52882491;p=src%2Fapp-framework-main.git diff --git a/src/wgtpkg-unit.c b/src/wgtpkg-unit.c index 48cf3bb..e01faa9 100644 --- a/src/wgtpkg-unit.c +++ b/src/wgtpkg-unit.c @@ -1,5 +1,5 @@ /* - Copyright 2016, 2017 IoT.bzh + Copyright (C) 2016-2019 IoT.bzh author: José Bollo @@ -28,7 +28,7 @@ #include #include - + #include "verbose.h" #include "utils-file.h" @@ -38,6 +38,7 @@ #include "utils-systemd.h" #include "wgtpkg-unit.h" +#include "wgt-strings.h" #if 0 #include @@ -53,8 +54,8 @@ static char *template; * Returns 1 if 'text' matches the 'pattern' or else returns 0. * When returning 1 and 'after' isn't NULL, the pointer to the * first character after the pettern in 'text' is stored in 'after'. - * The characters '\n' and ' ' have a special mening in the search: - * * '\n': matches any space or tabs (including none) followed + * The characters '\n' and ' ' have a special meaning in the search: + * * '\n': matches any space or tabs (including none) followed * either by '\n' or '\0' (end of the string) * * ' ': matches any space or tabs but at least one. */ @@ -116,12 +117,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; @@ -140,7 +142,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; @@ -155,7 +157,6 @@ static size_t pack(char *text, char purge) *write++ = *begin++; } } - cont = nextcont; } *write = 0; return (size_t)(write - text); @@ -217,7 +218,7 @@ static int process_one_unit(char *spec, struct unitdesc *desc) desc->type = unittype_service; name = nsrv; } - len = (size_t)(strchrnul(name, '\n') - name); + len = strcspn(name, " \t\n"); desc->name = strndup(name, len); desc->name_length = desc->name ? len : 0; } else { @@ -227,7 +228,7 @@ static int process_one_unit(char *spec, struct unitdesc *desc) } if (iswanted) { - len = (size_t)(strchrnul(wanted, '\n') - wanted); + len = strcspn(wanted, " \t\n"); desc->wanted_by = strndup(wanted, len); desc->wanted_by_length = len; } else { @@ -249,42 +250,75 @@ 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, struct json_object *jdesc) { int rc, rc2; - unsigned n; - char *beg, *end; - struct unitdesc *descs, *d; - - descs = NULL; - n = 0; + char *beg, *end, *befbeg, *aftend; + struct unitdesc *u; + struct generatedesc gdesc; + + gdesc.conf = conf; + gdesc.desc = jdesc; + gdesc.units = NULL; + gdesc.nunits = 0; rc = rc2 = 0; /* while there is a unit in the corpus */ - while(offset(corpus, "%begin systemd-unit\n", &beg)) { - - /* get the end of the unit */ - end = offset(beg, "%end systemd-unit\n", &corpus); + for(;;) { + befbeg = offset(corpus, "%begin ", &beg); + end = offset(corpus, "%end ", &aftend); + if (!befbeg) { + if (end) { + /* %end detected without %begin */ + ERROR("unexpected %%end at end"); + rc = rc ? :-EINVAL; + } + break; + } if (!end) { /* unterminated unit !! */ - ERROR("unterminated unit description!! %s", beg); + ERROR("unterminated unit description!!"); corpus = beg; rc2 = -EINVAL; + } else if (end < befbeg) { + /* sequence %end ... %begin detected !! */ + ERROR("unexpected %%end before %%begin"); + corpus = aftend; + rc2 = -EINVAL; } else { - /* separate the unit from the corpus */ - *end = 0; - - /* allocates a descriptor for the unit */ - d = realloc(descs, (n + 1) * sizeof *descs); - if (d == NULL) - rc2 = -ENOMEM; - else { - /* creates the unit description */ - memset(&d[n], 0, sizeof *d); - descs = d; - rc2 = process_one_unit(beg, &descs[n]); - if (rc2 >= 0) - n++; + befbeg = offset(beg, "%begin ", NULL); + if (befbeg && befbeg < end) { + /* sequence %begin ... %begin ... %end detected !! */ + ERROR("unexpected %%begin after %%begin"); + corpus = beg; + rc2 = -EINVAL; + } else { + *end = 0; + corpus = aftend; + if (matches("systemd-unit\n", beg, &beg)) { + if (!matches("systemd-unit\n", aftend, &corpus)) { + /* end doesnt match */ + ERROR("unmatched %%begin systemd-unit (matching end mismatch)"); + rc2 = -EINVAL; + } else { + /* allocates a descriptor for the unit */ + u = realloc((void*)gdesc.units, ((unsigned)gdesc.nunits + 1) * sizeof *gdesc.units); + if (u == NULL) + rc2 = -ENOMEM; + else { + /* creates the unit description */ + gdesc.units = u; + u = &u[gdesc.nunits]; + memset(u, 0, sizeof *u); + rc2 = process_one_unit(beg, u); + if (rc2 >= 0) + gdesc.nunits++; + } + } + } else { + ERROR("unexpected %%begin name"); + rc2 = -EINVAL; + } } } /* records the error if there is an error */ @@ -296,14 +330,14 @@ 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); + rc = process(closure, &gdesc); /* cleanup and frees */ - while(n) { - free((char *)(descs[--n].name)); - free((char *)(descs[n].wanted_by)); + while(gdesc.nunits) { + free((void*)(gdesc.units[--gdesc.nunits].name)); + free((void*)(gdesc.units[gdesc.nunits].wanted_by)); } - free(descs); + free((void*)gdesc.units); return rc; } @@ -311,7 +345,7 @@ static int process_all_units(char *corpus, int (*process)(void *closure, const s /* * Clear the unit generator */ -void unit_generator_off() +void unit_generator_close_template() { free(template); template = NULL; @@ -321,13 +355,13 @@ void unit_generator_off() * 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) +int unit_generator_open_template(const char *filename) { size_t size; char *tmp; int rc; - unit_generator_off(); + unit_generator_close_template(); rc = getfile(filename ? : FWK_UNIT_CONF, &template, NULL); if (!rc) { size = pack(template, ';'); @@ -338,28 +372,69 @@ int unit_generator_on(const char *filename) return rc; } +static int add_metadata(struct json_object *jdesc, const struct unitconf *conf) +{ + struct json_object *targets, *targ; + char portstr[30], afidstr[30]; + int port, afid, i, n; + + if (json_object_object_get_ex(jdesc, string_targets, &targets)) { + n = json_object_array_length(targets); + for (i = 0 ; i < n ; i++) { + targ = json_object_array_get_idx(targets, i); + if (!conf->new_afid) { + afid = 0; + port = 0; + } else { + afid = conf->new_afid(); + if (afid < 0) + return afid; + port = conf->base_http_ports + afid; + } + sprintf(afidstr, "%d", afid); + sprintf(portstr, "%d", port); + if (!j_add_many_strings_m(targ, + "#metatarget.http-port", portstr, + "#metatarget.afid", afidstr, + NULL)) + return -1; + } + } + + return j_add_many_strings_m(jdesc, + "#metadata.install-dir", conf->installdir, + "#metadata.icons-dir", conf->icondir, + 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'. + * was previously set using the function 'unit_generator_open_template'. * The callback function 'process' is then called with the * unit descriptors array and the expected closure. * 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_open_template(NULL); + if (!rc) { + instance = NULL; + rc = apply_mustach(template, jdesc, &instance, &size); + if (!rc) + rc = process_all_units(instance, conf, process, closure, jdesc); + free(instance); + } } return rc; } @@ -419,52 +494,26 @@ static int get_wants_target(char *path, size_t pathlen, const struct unitdesc *d return rc; } -static int do_send_reload(const struct unitdesc descs[], unsigned count) -{ - unsigned i; - int reloadsys, reloadusr; - - reloadsys = reloadusr = 0; - for (i = 0 ; i < count ; i++) { - if (descs[i].wanted_by != NULL) { - switch (descs[i].scope) { - case unitscope_user: - reloadusr = 1; - break; - case unitscope_system: - reloadsys = 1; - break; - default: - break; - } - } - } - - 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, rc2; - unsigned i; + int i; char path[PATH_MAX]; + const struct unitdesc *u; rc = 0; - for (i = 0 ; i < count ; i++) { - rc2 = check_unit_desc(&descs[i], 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, &descs[i]); + rc2 = get_unit_path(path, sizeof path, u); if (rc2 >= 0) { rc2 = unlink(path); } if (rc2 < 0 && rc == 0) rc = rc2; - if (descs[i].wanted_by != NULL) { - rc2 = get_wants_path(path, sizeof path, &descs[i]); + if (u->wanted_by != NULL) { + rc2 = get_wants_path(path, sizeof path, u); if (rc2 >= 0) rc2 = unlink(path); } @@ -472,29 +521,28 @@ static int do_uninstall_units(void *closure, const struct unitdesc descs[], unsi if (rc2 < 0 && rc == 0) rc = rc2; } - rc2 = do_send_reload(descs, count); - if (rc2 < 0 && rc == 0) - rc = rc2; return rc; } -static int do_install_units(void *closure, const struct unitdesc descs[], unsigned count) +static int do_install_units(void *closure, const struct generatedesc *desc) { int rc; - unsigned i; + int i; char path[PATH_MAX + 1], target[PATH_MAX + 1]; + const struct unitdesc *u; i = 0; - while (i < count) { - rc = check_unit_desc(&descs[i], 1); + while (i < desc->nunits) { + u = &desc->units[i]; + rc = check_unit_desc(u, 1); if (!rc) { - rc = get_unit_path(path, sizeof path, &descs[i]); + rc = get_unit_path(path, sizeof path, u); 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]); + 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, &descs[i]); + rc = get_wants_target(target, sizeof target, u); if (rc >= 0) { unlink(path); /* TODO? check? */ rc = symlink(target, path); @@ -507,34 +555,18 @@ static int do_install_units(void *closure, const struct unitdesc descs[], unsign if (rc < 0) goto error; } - rc = do_send_reload(descs, count); - if (rc < 0) - goto error; return 0; error: - do_uninstall_units(closure, descs, i); + i = errno; + do_uninstall_units(closure, desc); + errno = i; return rc; } -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) + const struct unitconf *conf, + int (*doer)(void *, const struct generatedesc *) ) { int rc; @@ -544,26 +576,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); }