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>
30 #include "utils-json.h"
35 struct json_object *pubarr;
36 struct json_object *direct;
37 struct json_object *byapp;
46 struct afm_db_dir *next;
53 struct afm_db_dir *dirhead;
54 struct afm_db_dir *dirtail;
55 struct afapps applications;
58 struct afm_db *afm_db_create()
60 struct afm_db *afdb = malloc(sizeof * afdb);
67 afdb->applications.pubarr = NULL;
68 afdb->applications.direct = NULL;
69 afdb->applications.byapp = NULL;
74 void afm_db_addref(struct afm_db *afdb)
80 void afm_db_unref(struct afm_db *afdb)
82 struct afm_db_dir *dir;
84 if (!--afdb->refcount) {
85 json_object_put(afdb->applications.pubarr);
86 json_object_put(afdb->applications.direct);
87 json_object_put(afdb->applications.byapp);
88 while (afdb->dirhead != NULL) {
90 afdb->dirhead = dir->next;
98 int add_dir(struct afm_db *afdb, const char *path, enum dir_type type)
100 struct afm_db_dir *dir;
105 /* don't depend on the cwd and unique name */
106 r = realpath(path, NULL);
110 /* avoiding duplications */
112 while(dir != NULL && (strcmp(dir->path, path) || dir->type != type))
119 /* allocates the structure */
120 dir = malloc(sizeof * dir);
131 if (afdb->dirtail == NULL)
134 afdb->dirtail->next = dir;
139 int afm_db_add_root(struct afm_db *afdb, const char *path)
141 return add_dir(afdb, path, type_root);
144 int afm_db_add_application(struct afm_db *afdb, const char *path)
146 return add_dir(afdb, path, type_app);
149 static int addapp(struct afapps *apps, const char *path)
151 struct wgt_info *info;
152 const struct wgt_desc *desc;
153 const struct wgt_desc_feature *feat;
154 struct json_object *priv = NULL, *pub, *bya, *plugs, *str;
156 /* connect to the widget */
157 info = wgt_info_createat(AT_FDCWD, path, 0, 1, 0);
160 return 0; /* silently ignore bad directories */
163 desc = wgt_info_desc(info);
165 /* create the application structure */
166 priv = json_object_new_object();
170 pub = json_object_new_object();
174 if (!j_add(priv, "public", pub)) {
175 json_object_put(pub);
179 plugs = json_object_new_array();
183 if (!j_add(priv, "plugins", plugs)) {
184 json_object_put(plugs);
188 if(!j_add_string(priv, "id", desc->id)
189 || !j_add_string(priv, "path", path)
190 || !j_add_string(priv, "content", desc->content_src)
191 || !j_add_string(priv, "type", desc->content_type)
192 || !j_add_string(pub, "id", desc->idaver)
193 || !j_add_string(pub, "version", desc->version)
194 || !j_add_integer(pub, "width", desc->width)
195 || !j_add_integer(pub, "height", desc->height)
196 || !j_add_string(pub, "name", desc->name)
197 || !j_add_string(pub, "description", desc->description)
198 || !j_add_string(pub, "shortname", desc->name_short)
199 || !j_add_string(pub, "author", desc->author))
202 feat = desc->features;
204 static const char prefix[] = FWK_PREFIX_PLUGIN;
205 if (!memcmp(feat->name, prefix, sizeof prefix - 1)) {
206 str = json_object_new_string (feat->name + sizeof prefix - 1);
209 if (json_object_array_add(plugs, str)) {
210 json_object_put(str);
217 /* record the application structure */
218 if (!json_object_object_get_ex(apps->byapp, desc->id, &bya)) {
219 bya = json_object_new_object();
222 if (!j_add(apps->byapp, desc->id, bya)) {
223 json_object_put(bya);
228 if (!j_add(apps->direct, desc->idaver, priv))
230 json_object_get(priv);
232 if (!j_add(bya, desc->version, priv)) {
233 json_object_put(priv);
237 if (json_object_array_add(apps->pubarr, pub))
240 wgt_info_unref(info);
244 json_object_put(priv);
245 wgt_info_unref(info);
256 static int enumentries(struct enumdata *data, int (*callto)(struct enumdata *))
261 struct dirent entry, *e;
263 /* opens the directory */
264 dir = opendir(data->path);
268 /* prepare appending entry names */
269 beg = data->path + data->length;
272 /* enumerate entries */
273 rc = readdir_r(dir, &entry, &e);
275 if (entry.d_name[0] != '.' || (entry.d_name[1] && (entry.d_name[1] != '.' || entry.d_name[2]))) {
277 end = stpcpy(beg, entry.d_name);
278 data->length = end - data->path;
279 /* call the function */
284 rc = readdir_r(dir, &entry, &e);
290 static int recordapp(struct enumdata *data)
292 return addapp(&data->apps, data->path);
295 /* enumerate the versions */
296 static int enumvers(struct enumdata *data)
298 int rc = enumentries(data, recordapp);
299 return !rc || errno != ENOTDIR ? 0 : rc;
302 /* regenerate the list of applications */
303 int afm_db_update_applications(struct afm_db *afdb)
306 struct enumdata edata;
307 struct afapps oldapps;
308 struct afm_db_dir *dir;
310 /* create the result */
311 edata.apps.pubarr = json_object_new_array();
312 edata.apps.direct = json_object_new_object();
313 edata.apps.byapp = json_object_new_object();
314 if (edata.apps.pubarr == NULL || edata.apps.direct == NULL || edata.apps.byapp == NULL) {
319 for (dir = afdb->dirhead ; dir != NULL ; dir = dir->next) {
320 if (dir->type == type_root) {
321 edata.length = stpcpy(edata.path, dir->path) - edata.path;
322 assert(edata.length < sizeof edata.path);
323 /* enumerate the applications */
324 rc = enumentries(&edata, enumvers);
328 rc = addapp(&edata.apps, dir->path);
331 /* commit the result */
332 oldapps = afdb->applications;
333 afdb->applications = edata.apps;
334 json_object_put(oldapps.pubarr);
335 json_object_put(oldapps.direct);
336 json_object_put(oldapps.byapp);
340 json_object_put(edata.apps.pubarr);
341 json_object_put(edata.apps.direct);
342 json_object_put(edata.apps.byapp);
346 int afm_db_ensure_applications(struct afm_db *afdb)
348 return afdb->applications.pubarr ? 0 : afm_db_update_applications(afdb);
351 struct json_object *afm_db_application_list(struct afm_db *afdb)
353 return afm_db_ensure_applications(afdb) ? NULL : json_object_get(afdb->applications.pubarr);
356 struct json_object *afm_db_get_application(struct afm_db *afdb, const char *id)
358 struct json_object *result;
359 if (!afm_db_ensure_applications(afdb) && json_object_object_get_ex(afdb->applications.direct, id, &result))
360 return json_object_get(result);
364 struct json_object *afm_db_get_application_public(struct afm_db *afdb, const char *id)
366 struct json_object *result = afm_db_get_application(afdb, id);
367 return result && json_object_object_get_ex(result, "public", &result) ? json_object_get(result) : NULL;
373 #if defined(TESTAPPFWK)
377 struct afm_db *afdb = afm_db_create();
378 afm_db_add_root(afdb,FWK_APP_DIR);
379 afm_db_update_applications(afdb);
380 printf("array = %s\n", json_object_to_json_string_ext(afdb->applications.pubarr, 3));
381 printf("direct = %s\n", json_object_to_json_string_ext(afdb->applications.direct, 3));
382 printf("byapp = %s\n", json_object_to_json_string_ext(afdb->applications.byapp, 3));