6dc7182fbc8f1a709ffed77eaa5e65c61473399b
[src/app-framework-main.git] / src / appfwk.c
1 /*
2  Copyright 2015 IoT.bzh
3
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8      http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16
17 #include <stdlib.h>
18 #include <assert.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <dirent.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25
26 #include <wgt.h>
27
28 struct stringset {
29         int count;
30         char **strings;
31 };
32  
33
34 struct appfwk {
35         int refcount;
36         struct stringset paths;
37 };
38
39 struct appfwk *appfwk_create()
40 {
41         struct appfwk *appfwk = malloc(sizeof * appfwk);
42         if (!appfwk)
43                 errno = ENOMEM;
44         else {
45                 appfwk->refcount = 1;
46                 appfwk->paths.count = 0;
47                 appfwk->paths.strings = NULL;
48         }
49         return appfwk;
50 }
51
52 void appfwk_addref(struct appfwk *appfwk)
53 {
54         assert(appfwk);
55         appfwk->refcount++;
56 }
57
58 void appfwk_unref(struct appfwk *appfwk)
59 {
60         assert(appfwk);
61         if (!--appfwk->refcount) {
62                 while (appfwk->paths.count)
63                         free(appfwk->paths.strings[--appfwk->paths.count]);
64                 free(appfwk);
65         }
66 }
67
68 int appfwk_add_root(struct appfwk *appfwk, const char *path)
69 {
70         int i, n;
71         char *r, **roots;
72         assert(appfwk);
73         r = realpath(path, NULL);
74         if (!r)
75                 return -1;
76
77         /* avoiding duplications */
78         n = appfwk->paths.count;
79         roots = appfwk->paths.strings;
80         for (i = 0 ; i < n ; i++)
81                 if (!strcmp(r, roots[i])) {
82                         free(r);
83                         return 0;
84                 }
85
86         /* add */
87         roots = realloc(roots, (n + 1) * sizeof(roots[0]));
88         if (!roots) {
89                 free(r);
90                 errno = ENOMEM;
91                 return -1;
92         }
93         roots[n++] = r;
94         appfwk->paths.strings = roots;
95         appfwk->paths.count = n;
96         return 0;
97 }
98
99 struct aea {
100         char *path;
101         char *appver;
102         char *ver;
103         const char *root;
104         const char *appid;
105         const char *version;
106         int (*callback)(struct wgt *wgt, void *data);
107         void *data;
108 };
109
110 struct appfwk_enumerate_applications_context {
111         const char *dirpath;
112         const char *appid;
113         const char *version;
114         
115         void *data;
116 };
117
118 inline int testd(int dirfd, struct dirent *e)
119 {
120         return e->d_name[0] != '.' || (e->d_name[1] && (e->d_name[1] != '.' || e->d_name[2]));
121 }
122
123 #include <stdio.h>
124 static int aea3(int dirfd, struct aea *aea)
125 {
126         printf("aea3 %s *** %s *** %s\n", aea->path, aea->appver, aea->ver);
127         return 0;
128 }
129
130 static int aea2(int dirfd, struct aea *aea)
131 {
132         DIR *dir;
133         int rc, fd;
134         struct dirent entry, *e;
135
136         dir = fdopendir(dirfd);
137         if (!dir)
138                 return -1;
139
140         aea->version = entry.d_name;
141
142         rc = readdir_r(dir, &entry, &e);
143         while (!rc && e) {
144                 if (testd(dirfd, &entry)) {
145                         fd = openat(dirfd, entry.d_name, O_DIRECTORY|O_RDONLY);
146                         if (fd >= 0) {
147                                 strcpy(aea->ver, entry.d_name);
148                                 rc = aea3(fd, aea);                     
149                                 close(fd);
150                         }
151                 }       
152                 rc = readdir_r(dir, &entry, &e);
153         }
154         closedir(dir);
155         return rc;
156 }
157
158 static int aea1(int dirfd, struct aea *aea)
159 {
160         DIR *dir;
161         int rc, fd;
162         struct dirent entry, *e;
163
164         dir = fdopendir(dirfd);
165         if (!dir)
166                 return -1;
167
168         aea->appid = entry.d_name;
169
170         rc = readdir_r(dir, &entry, &e);
171         while (!rc && e) {
172                 if (testd(dirfd, &entry)) {
173                         fd = openat(dirfd, entry.d_name, O_DIRECTORY|O_RDONLY);
174                         if (fd >= 0) {
175                                 aea->ver = stpcpy(aea->appver, entry.d_name);
176                                 *aea->ver++ = '/';
177                                 rc = aea2(fd, aea);                     
178                                 close(fd);
179                         }
180                 }       
181                 rc = readdir_r(dir, &entry, &e);
182         }
183         closedir(dir);
184         return rc;
185 }
186
187 int appfwk_enumerate_applications(struct appfwk *appfwk, int (*callback)(struct wgt *wgt, void *data), void *data)
188 {
189         int rc, iroot, nroots;
190         char **roots;
191         int fd;
192         char buffer[PATH_MAX];
193         struct aea aea;
194
195         aea.callback = callback;
196         aea.data = data;
197         aea.path = buffer;
198
199         nroots = appfwk->paths.count;
200         roots = appfwk->paths.strings;
201         for (iroot = 0 ; iroot < nroots ; iroot++) {
202                 aea.root = roots[iroot];
203                 fd = openat(AT_FDCWD, aea.root, O_DIRECTORY|O_RDONLY);
204                 if (fd >= 0) {
205                         aea.appver = stpcpy(buffer, aea.root);
206                         *aea.appver++ = '/';
207                         rc = aea1(fd, &aea);
208                         close(fd);
209                 }
210         }
211         return 0;
212 }
213 /*
214         struct wgt *wgt;
215                 wgt = wgt_create();
216                 if (!wgt)
217                         return -1;
218                 wgt_unref(wgt);
219
220         rfd = AT_FDCWD;
221         if (pathname) {
222                 rfd = openat(rfd, pathname, O_PATH|O_DIRECTORY);
223 */
224