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;
174 /* connect to the widget */
175 info = wgt_info_createat(AT_FDCWD, path, 0, 1, 0);
178 return 0; /* silently ignore bad directories */
181 desc = wgt_info_desc(info);
183 /* create the application id */
184 appid = alloca(2 + strlen(desc->id) + strlen(desc->version));
185 end = stpcpy(appid, desc->id);
187 strcpy(end, desc->version);
189 /* create the application structure */
190 priv = json_object_new_object();
194 pub = json_object_new_object();
198 if (json_add(priv, "public", pub)) {
199 json_object_put(pub);
203 plugs = json_object_new_array();
207 if (json_add(priv, "plugins", plugs)) {
208 json_object_put(plugs);
212 if(json_add_str(priv, "id", desc->id)
213 || json_add_str(priv, "path", path)
214 || json_add_str(priv, "content", desc->content_src)
215 || json_add_str(priv, "type", desc->content_type)
216 || json_add_str(pub, "id", appid)
217 || json_add_str(pub, "version", desc->version)
218 || json_add_int(pub, "width", desc->width)
219 || json_add_int(pub, "height", desc->height)
220 || json_add_str(pub, "name", desc->name)
221 || json_add_str(pub, "description", desc->description)
222 || json_add_str(pub, "shortname", desc->name_short)
223 || json_add_str(pub, "author", desc->author))
226 feat = desc->features;
228 static const char prefix[] = FWK_PREFIX_PLUGIN;
229 if (!memcmp(feat->name, prefix, sizeof prefix - 1)) {
230 str = json_object_new_string (feat->name + sizeof prefix - 1);
233 if (json_object_array_add(plugs, str)) {
234 json_object_put(str);
241 /* record the application structure */
242 if (!json_object_object_get_ex(apps->byapp, desc->id, &bya)) {
243 bya = json_object_new_object();
246 if (json_add(apps->byapp, desc->id, bya)) {
247 json_object_put(bya);
252 if (json_add(apps->direct, appid, priv))
254 json_object_get(priv);
256 if (json_add(bya, desc->version, priv)) {
257 json_object_put(priv);
261 if (json_object_array_add(apps->pubarr, pub))
264 wgt_info_unref(info);
268 json_object_put(priv);
269 wgt_info_unref(info);
280 static int enumentries(struct enumdata *data, int (*callto)(struct enumdata *))
285 struct dirent entry, *e;
287 /* opens the directory */
288 dir = opendir(data->path);
292 /* prepare appending entry names */
293 beg = data->path + data->length;
296 /* enumerate entries */
297 rc = readdir_r(dir, &entry, &e);
299 if (entry.d_name[0] != '.' || (entry.d_name[1] && (entry.d_name[1] != '.' || entry.d_name[2]))) {
301 end = stpcpy(beg, entry.d_name);
302 data->length = end - data->path;
303 /* call the function */
308 rc = readdir_r(dir, &entry, &e);
314 static int recordapp(struct enumdata *data)
316 return addapp(&data->apps, data->path);
319 /* enumerate the versions */
320 static int enumvers(struct enumdata *data)
322 int rc = enumentries(data, recordapp);
323 return !rc || errno != ENOTDIR ? 0 : rc;
326 /* regenerate the list of applications */
327 int afm_db_update_applications(struct afm_db *afdb)
330 struct enumdata edata;
331 struct afapps oldapps;
332 struct afm_db_dir *dir;
334 /* create the result */
335 edata.apps.pubarr = json_object_new_array();
336 edata.apps.direct = json_object_new_object();
337 edata.apps.byapp = json_object_new_object();
338 if (edata.apps.pubarr == NULL || edata.apps.direct == NULL || edata.apps.byapp == NULL) {
343 for (dir = afdb->dirhead ; dir != NULL ; dir = dir->next) {
344 if (dir->type == type_root) {
345 edata.length = stpcpy(edata.path, dir->path) - edata.path;
346 assert(edata.length < sizeof edata.path);
347 /* enumerate the applications */
348 rc = enumentries(&edata, enumvers);
352 rc = addapp(&edata.apps, dir->path);
355 /* commit the result */
356 oldapps = afdb->applications;
357 afdb->applications = edata.apps;
358 json_object_put(oldapps.pubarr);
359 json_object_put(oldapps.direct);
360 json_object_put(oldapps.byapp);
364 json_object_put(edata.apps.pubarr);
365 json_object_put(edata.apps.direct);
366 json_object_put(edata.apps.byapp);
370 int afm_db_ensure_applications(struct afm_db *afdb)
372 return afdb->applications.pubarr ? 0 : afm_db_update_applications(afdb);
375 struct json_object *afm_db_application_list(struct afm_db *afdb)
377 return afm_db_ensure_applications(afdb) ? NULL : json_object_get(afdb->applications.pubarr);
380 struct json_object *afm_db_get_application(struct afm_db *afdb, const char *id)
382 struct json_object *result;
383 if (!afm_db_ensure_applications(afdb) && json_object_object_get_ex(afdb->applications.direct, id, &result))
384 return json_object_get(result);
388 struct json_object *afm_db_get_application_public(struct afm_db *afdb, const char *id)
390 struct json_object *result = afm_db_get_application(afdb, id);
391 return result && json_object_object_get_ex(result, "public", &result) ? json_object_get(result) : NULL;
397 #if defined(TESTAPPFWK)
401 struct afm_db *afdb = afm_db_create();
402 afm_db_add_root(afdb,FWK_APP_DIR);
403 afm_db_update_applications(afdb);
404 printf("array = %s\n", json_object_to_json_string_ext(afdb->applications.pubarr, 3));
405 printf("direct = %s\n", json_object_to_json_string_ext(afdb->applications.direct, 3));
406 printf("byapp = %s\n", json_object_to_json_string_ext(afdb->applications.byapp, 3));