4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
26 #include <sys/types.h>
34 struct json_object *pubarr;
35 struct json_object *direct;
36 struct json_object *byapp;
45 struct afm_db_dir *next;
52 struct afm_db_dir *dirhead;
53 struct afm_db_dir *dirtail;
54 struct afapps applications;
57 struct afm_db *afm_db_create()
59 struct afm_db *afdb = malloc(sizeof * afdb);
66 afdb->applications.pubarr = NULL;
67 afdb->applications.direct = NULL;
68 afdb->applications.byapp = NULL;
73 void afm_db_addref(struct afm_db *afdb)
79 void afm_db_unref(struct afm_db *afdb)
81 struct afm_db_dir *dir;
83 if (!--afdb->refcount) {
84 json_object_put(afdb->applications.pubarr);
85 json_object_put(afdb->applications.direct);
86 json_object_put(afdb->applications.byapp);
87 while (afdb->dirhead != NULL) {
89 afdb->dirhead = dir->next;
97 int add_dir(struct afm_db *afdb, const char *path, enum dir_type type)
99 struct afm_db_dir *dir;
104 /* don't depend on the cwd and unique name */
105 r = realpath(path, NULL);
109 /* avoiding duplications */
111 while(dir != NULL && (strcmp(dir->path, path) || dir->type != type))
118 /* allocates the structure */
119 dir = malloc(sizeof * dir);
130 if (afdb->dirtail == NULL)
133 afdb->dirtail->next = dir;
138 int afm_db_add_root(struct afm_db *afdb, const char *path)
140 return add_dir(afdb, path, type_root);
143 int afm_db_add_application(struct afm_db *afdb, const char *path)
145 return add_dir(afdb, path, type_app);
148 static int json_add(struct json_object *obj, const char *key, struct json_object *val)
150 json_object_object_add(obj, key, val);
154 static int json_add_str(struct json_object *obj, const char *key, const char *val)
156 struct json_object *str = json_object_new_string (val ? val : "");
157 return str ? json_add(obj, key, str) : -1;
160 static int json_add_int(struct json_object *obj, const char *key, int val)
162 struct json_object *v = json_object_new_int (val);
163 return v ? json_add(obj, key, v) : -1;
166 static int addapp(struct afapps *apps, const char *path)
168 struct wgt_info *info;
169 const struct wgt_desc *desc;
170 const struct wgt_desc_feature *feat;
171 struct json_object *priv = NULL, *pub, *bya, *plugs, *str;
173 /* connect to the widget */
174 info = wgt_info_createat(AT_FDCWD, path, 0, 1, 0);
177 return 0; /* silently ignore bad directories */
180 desc = wgt_info_desc(info);
182 /* create the application structure */
183 priv = json_object_new_object();
187 pub = json_object_new_object();
191 if (json_add(priv, "public", pub)) {
192 json_object_put(pub);
196 plugs = json_object_new_array();
200 if (json_add(priv, "plugins", plugs)) {
201 json_object_put(plugs);
205 if(json_add_str(priv, "id", desc->id)
206 || json_add_str(priv, "path", path)
207 || json_add_str(priv, "content", desc->content_src)
208 || json_add_str(priv, "type", desc->content_type)
209 || json_add_str(pub, "id", desc->idaver)
210 || json_add_str(pub, "version", desc->version)
211 || json_add_int(pub, "width", desc->width)
212 || json_add_int(pub, "height", desc->height)
213 || json_add_str(pub, "name", desc->name)
214 || json_add_str(pub, "description", desc->description)
215 || json_add_str(pub, "shortname", desc->name_short)
216 || json_add_str(pub, "author", desc->author))
219 feat = desc->features;
221 static const char prefix[] = FWK_PREFIX_PLUGIN;
222 if (!memcmp(feat->name, prefix, sizeof prefix - 1)) {
223 str = json_object_new_string (feat->name + sizeof prefix - 1);
226 if (json_object_array_add(plugs, str)) {
227 json_object_put(str);
234 /* record the application structure */
235 if (!json_object_object_get_ex(apps->byapp, desc->id, &bya)) {
236 bya = json_object_new_object();
239 if (json_add(apps->byapp, desc->id, bya)) {
240 json_object_put(bya);
245 if (json_add(apps->direct, desc->idaver, priv))
247 json_object_get(priv);
249 if (json_add(bya, desc->version, priv)) {
250 json_object_put(priv);
254 if (json_object_array_add(apps->pubarr, pub))
257 wgt_info_unref(info);
261 json_object_put(priv);
262 wgt_info_unref(info);
273 static int enumentries(struct enumdata *data, int (*callto)(struct enumdata *))
278 struct dirent entry, *e;
280 /* opens the directory */
281 dir = opendir(data->path);
285 /* prepare appending entry names */
286 beg = data->path + data->length;
289 /* enumerate entries */
290 rc = readdir_r(dir, &entry, &e);
292 if (entry.d_name[0] != '.' || (entry.d_name[1] && (entry.d_name[1] != '.' || entry.d_name[2]))) {
294 end = stpcpy(beg, entry.d_name);
295 data->length = end - data->path;
296 /* call the function */
301 rc = readdir_r(dir, &entry, &e);
307 static int recordapp(struct enumdata *data)
309 return addapp(&data->apps, data->path);
312 /* enumerate the versions */
313 static int enumvers(struct enumdata *data)
315 int rc = enumentries(data, recordapp);
316 return !rc || errno != ENOTDIR ? 0 : rc;
319 /* regenerate the list of applications */
320 int afm_db_update_applications(struct afm_db *afdb)
323 struct enumdata edata;
324 struct afapps oldapps;
325 struct afm_db_dir *dir;
327 /* create the result */
328 edata.apps.pubarr = json_object_new_array();
329 edata.apps.direct = json_object_new_object();
330 edata.apps.byapp = json_object_new_object();
331 if (edata.apps.pubarr == NULL || edata.apps.direct == NULL || edata.apps.byapp == NULL) {
336 for (dir = afdb->dirhead ; dir != NULL ; dir = dir->next) {
337 if (dir->type == type_root) {
338 edata.length = stpcpy(edata.path, dir->path) - edata.path;
339 assert(edata.length < sizeof edata.path);
340 /* enumerate the applications */
341 rc = enumentries(&edata, enumvers);
345 rc = addapp(&edata.apps, dir->path);
348 /* commit the result */
349 oldapps = afdb->applications;
350 afdb->applications = edata.apps;
351 json_object_put(oldapps.pubarr);
352 json_object_put(oldapps.direct);
353 json_object_put(oldapps.byapp);
357 json_object_put(edata.apps.pubarr);
358 json_object_put(edata.apps.direct);
359 json_object_put(edata.apps.byapp);
363 int afm_db_ensure_applications(struct afm_db *afdb)
365 return afdb->applications.pubarr ? 0 : afm_db_update_applications(afdb);
368 struct json_object *afm_db_application_list(struct afm_db *afdb)
370 return afm_db_ensure_applications(afdb) ? NULL : json_object_get(afdb->applications.pubarr);
373 struct json_object *afm_db_get_application(struct afm_db *afdb, const char *id)
375 struct json_object *result;
376 if (!afm_db_ensure_applications(afdb) && json_object_object_get_ex(afdb->applications.direct, id, &result))
377 return json_object_get(result);
381 struct json_object *afm_db_get_application_public(struct afm_db *afdb, const char *id)
383 struct json_object *result = afm_db_get_application(afdb, id);
384 return result && json_object_object_get_ex(result, "public", &result) ? json_object_get(result) : NULL;
390 #if defined(TESTAPPFWK)
394 struct afm_db *afdb = afm_db_create();
395 afm_db_add_root(afdb,FWK_APP_DIR);
396 afm_db_update_applications(afdb);
397 printf("array = %s\n", json_object_to_json_string_ext(afdb->applications.pubarr, 3));
398 printf("direct = %s\n", json_object_to_json_string_ext(afdb->applications.direct, 3));
399 printf("byapp = %s\n", json_object_to_json_string_ext(afdb->applications.byapp, 3));