X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafm-udb.c;h=be1a5d3179a03e90aecce3bcb9eab7a54221dc0d;hb=3f53c6fff76d6200ebf2165f5d206684a142db35;hp=9b1a3548c15d1329b73650b2063f9f25154a01b3;hpb=550ca0ae2bb9138c85fda941b67d4db1da1609ed;p=src%2Fapp-framework-main.git diff --git a/src/afm-udb.c b/src/afm-udb.c index 9b1a354..be1a5d3 100644 --- a/src/afm-udb.c +++ b/src/afm-udb.c @@ -1,5 +1,5 @@ /* - Copyright 2015, 2016, 2017 IoT.bzh + Copyright (C) 2015-2018 IoT.bzh author: José Bollo @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -33,7 +34,6 @@ #include "afm-udb.h" - static const char x_afm_prefix[] = "X-AFM-"; static const char service_extension[] = ".service"; static const char key_unit_path[] = "-unit-path"; @@ -78,6 +78,11 @@ struct afm_updt { struct afm_apps applications; }; +/* + * The default language + */ +static char *default_lang; + /* * Release the data of the afm_apps object 'apps'. */ @@ -89,6 +94,41 @@ static void apps_put(struct afm_apps *apps) json_object_put(apps->prvobj); } +/* + * Append the field 'data' to the field 'name' of the 'object'. + * When a second append is done to one field, it is automatically + * transformed to an array. + * Return 0 in case of success or -1 in case of error. + */ +static int append_field( + struct json_object *object, + const char *name, + struct json_object *data +) +{ + struct json_object *item, *array; + + if (!json_object_object_get_ex(object, name, &item)) + json_object_object_add(object, name, data); + else { + if (json_object_is_type(item, json_type_array)) + array = item; + else { + array = json_object_new_array(); + if (!array) + goto error; + json_object_array_add(array, json_object_get(item)); + json_object_object_add(object, name, array); + } + json_object_array_add(array, data); + } + return 0; + error: + json_object_put(data); + errno = ENOMEM; + return -1; +} + /* * Adds the field of 'name' and 'value' in 'priv' and also if possible in 'pub' * Returns 0 on success or -1 on error. @@ -121,10 +161,10 @@ static int add_field( /* add the value */ if (name[0] == '-') { - json_object_object_add(priv, &name[1], v); + append_field(priv, &name[1], v); } else { - json_object_object_add(priv, name, json_object_get(v)); - json_object_object_add(pub, name, v); + append_field(priv, name, json_object_get(v)); + append_field(pub, name, v); } return 0; } @@ -189,6 +229,7 @@ static int addunit( { struct json_object *priv, *pub, *id; const char *strid; + size_t len; /* create the application structure */ priv = json_object_new_object(); @@ -199,6 +240,11 @@ static int addunit( if (!pub) goto error; + /* make the unit name */ + len = strlen(unitname); + assert(len >= (sizeof service_extension - 1)); + assert(!memcmp(&unitname[len - (sizeof service_extension - 1)], service_extension, sizeof service_extension)); + /* adds the values */ if (add_fields_of_content(priv, pub, content, length) || add_field(priv, pub, key_unit_path, unitpath) @@ -228,6 +274,69 @@ error: return -1; } +/* + * read a unit file + */ +static int read_unit_file(const char *path, char **content, size_t *length) +{ + int rc, st; + char c, *read, *write; + + /* read the file */ + rc = getfile(path, content, length); + if (rc >= 0) { + /* removes any comment and join continued lines */ + st = 0; + read = write = *content; + for (;;) { + do { c = *read++; } while (c == '\r'); + if (!c) + break; + switch (st) { + case 0: + /* state 0: begin of a line */ + if (c == ';' || c == '#') { + st = 3; /* removes lines starting with ; or # */ + break; + } + if (c == '\n') + break; /* removes empty lines */ +enter_state_1: + st = 1; + /*@fallthrough@*/ + case 1: + /* state 1: emitting a normal line */ + if (c == '\\') + st = 2; + else { + *write++ = c; + if (c == '\n') + st = 0; + } + break; + case 2: + /* state 2: character after '\' */ + if (c == '\n') + c = ' '; + else + *write++ = '\\'; + goto enter_state_1; + case 3: + /* state 3: inside a comment, wait its end */ + if (c == '\n') + st = 0; + break; + } + } + if (st == 1) + *write++ = '\n'; + *write = 0; + *length = (size_t)(write - *content); + *content = realloc(*content, *length + 1); + } + return rc; +} + /* * called for each unit */ @@ -249,14 +358,16 @@ static int update_cb(void *closure, const char *name, const char *path, int isus return 0; /* reads the file */ - rc = getfile(path, &content, &length); + rc = read_unit_file(path, &content, &length); if (rc < 0) - return rc; + return 0; /* process the file */ rc = addunit(&updt->applications, isuser, path, name, content, length); + /* TODO: if (rc < 0) + ERROR("Ignored boggus unit %s (error: %m)", path); */ free(content); - return rc; + return 0; } /* @@ -354,22 +465,29 @@ int afm_udb_update(struct afm_udb *afudb) tmp = afudb->applications; afudb->applications = updt.applications; apps_put(&tmp); - afm_udb_addref(afudb); + afm_udb_unref(afudb); return 0; error: apps_put(&updt.applications); - afm_udb_addref(afudb); + afm_udb_unref(afudb); return -1; } +void afm_udb_set_default_lang(const char *lang) +{ + char *oldval = default_lang; + default_lang = lang ? strdup(lang) : NULL; + free(oldval); +} + /* * Get the list of the applications private data of the afm_udb object 'afudb'. * The list is returned as a JSON-array that must be released using * 'json_object_put'. * Returns NULL in case of error. */ -struct json_object *afm_udb_applications_private(struct afm_udb *afudb) +struct json_object *afm_udb_applications_private(struct afm_udb *afudb, int uid) { return json_object_get(afudb->applications.prvarr); } @@ -380,7 +498,7 @@ struct json_object *afm_udb_applications_private(struct afm_udb *afudb) * 'json_object_put'. * Returns NULL in case of error. */ -struct json_object *afm_udb_applications_public(struct afm_udb *afudb) +struct json_object *afm_udb_applications_public(struct afm_udb *afudb, int uid, const char *lang) { return json_object_get(afudb->applications.pubarr); } @@ -390,7 +508,7 @@ struct json_object *afm_udb_applications_public(struct afm_udb *afudb) * It returns a JSON-object that must be released using 'json_object_put'. * Returns NULL in case of error. */ -static struct json_object *get_no_case(struct json_object *object, const char *id) +static struct json_object *get_no_case(struct json_object *object, const char *id, int uid, const char *lang) { struct json_object *result; struct json_object_iter i; @@ -412,9 +530,9 @@ static struct json_object *get_no_case(struct json_object *object, const char *i * It returns a JSON-object that must be released using 'json_object_put'. * Returns NULL in case of error. */ -struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const char *id) +struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const char *id, int uid) { - return get_no_case(afudb->applications.prvobj, id); + return get_no_case(afudb->applications.prvobj, id, uid, NULL); } /* @@ -423,9 +541,9 @@ struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const * Returns NULL in case of error. */ struct json_object *afm_udb_get_application_public(struct afm_udb *afudb, - const char *id) + const char *id, int uid, const char *lang) { - return get_no_case(afudb->applications.pubobj, id); + return get_no_case(afudb->applications.pubobj, id, uid, lang); }