Fix multiple delimiter
[platform/core/appfw/launchpad.git] / src / loader_info.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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 #define _GNU_SOURCE
17
18 #include <stdio.h>
19 #include <malloc.h>
20 #include <stdlib.h>
21 #include <dirent.h>
22 #include <string.h>
23
24 #include "loader_info.h"
25 #include "launchpad_common.h"
26
27 #define TAG_LOADER      "[LOADER]"
28 #define TAG_NAME        "NAME"
29 #define TAG_EXE         "EXE"
30 #define TAG_APP_TYPE    "APP_TYPE"
31 #define TAG_DETECTION_METHOD    "DETECTION_METHOD"
32 #define TAG_TIMEOUT     "TIMEOUT"
33 #define TAG_EXTRA       "EXTRA"
34 #define TAG_EXTRA_ARRAY         "EXTRA_ARRAY"
35 #define TAG_EXTRA_ARRAY_VAL     "EXTRA_ARRAY_VAL"
36 #define TAG_ALTERNATIVE_LOADER  "ALTERNATIVE_LOADER"
37 #define TAG_HW_ACC              "HW_ACC"
38 #define VAL_ON                  "ON"
39 #define VAL_OFF                 "OFF"
40 #define VAL_METHOD_TIMEOUT      "TIMEOUT"
41 #define VAL_METHOD_DEMAND       "DEMAND"
42 #define VAL_METHOD_VISIBILITY   "VISIBILITY"
43
44
45 static loader_info_t *__create_loader_info()
46 {
47         loader_info_t *info = malloc(sizeof(loader_info_t));
48
49         info->type = 0;
50         info->name = NULL;
51         info->exe = NULL;
52         info->app_types = NULL;
53         info->hw_acc = NULL;
54         info->alternative_loaders = NULL;
55         info->detection_method = METHOD_TIMEOUT | METHOD_VISIBILITY;
56         info->timeout_val = 5000;
57         info->extra = bundle_create();
58
59         return info;
60 }
61
62 static void __parse_detection_method(loader_info_t *info, char *line)
63 {
64         char *token;
65         char *savedptr;
66
67         token = strtok_r(line, " |\t\r\n", &savedptr);
68         info->detection_method = 0;
69         while (token) {
70                 if (!strcmp(token, VAL_METHOD_TIMEOUT))
71                         info->detection_method |= METHOD_TIMEOUT;
72                 else if (!strcmp(token, VAL_METHOD_VISIBILITY))
73                         info->detection_method |= METHOD_VISIBILITY;
74                 else if (!strcmp(token, VAL_METHOD_DEMAND))
75                         info->detection_method |= METHOD_DEMAND;
76
77                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
78         }
79
80         _D("detection_method:%d", info->detection_method);
81 }
82
83 static void __parse_app_types(loader_info_t *info, char *line)
84 {
85         char *token;
86         char *savedptr;
87
88         token = strtok_r(line, " |\t\r\n", &savedptr);
89         while (token) {
90                 info->app_types = g_list_append(info->app_types, strdup(token));
91                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
92         }
93 }
94
95 static void __parse_extra(loader_info_t *info, char *line)
96 {
97         char *tok1 = NULL;
98         char *tok2 = NULL;
99         char *tok3 = NULL;
100
101         if (info->extra == NULL)
102                 return;
103
104         sscanf(line, "%ms %ms %ms", &tok1, &tok2, &tok3);
105
106         if (!tok1 || !tok2 || !tok3)
107                 goto end;
108
109         if (strlen(tok2) == 0 || strlen(tok3) == 0)
110                 goto end;
111
112         bundle_add_str(info->extra, tok2, tok3);
113
114 end:
115         if (tok1)
116                 free(tok1);
117         if (tok2)
118                 free(tok2);
119         if (tok3)
120                 free(tok3);
121 }
122
123 static void __add_extra_array_from_list(bundle *b, const char *key, GList *list)
124 {
125         const char **array;
126         int len;
127         int i;
128         GList *cur;
129
130         if (b == NULL || key == NULL || list == NULL)
131                 return;
132
133         len = g_list_length(list);
134         array = malloc(sizeof(const char *) * len);
135
136         cur = list;
137         for (i = 0; i < len; i++) {
138                 array[i] = cur->data;
139                 cur = g_list_next(cur);
140         }
141
142         bundle_add_str_array(b, key, array, len);
143         free(array);
144 }
145
146 static void __flush_extra_array(bundle *b, char *key, GList *list)
147 {
148         if (list) {
149                 __add_extra_array_from_list(b, key, list);
150                 g_list_free_full(list, free);
151         }
152
153         free(key);
154 }
155
156 static GList *__parse_file(GList *list, const char *path)
157 {
158         FILE *fp;
159         char buf[LINE_MAX];
160         char *tok1 = NULL;
161         char *tok2 = NULL;
162         loader_info_t *cur_info = NULL;
163         char *key = NULL;
164         GList *extra_array = NULL;
165
166         fp = fopen(path, "rt");
167         if (fp == NULL)
168                 return list;
169
170         while (fgets(buf, sizeof(buf), fp) != NULL) {
171                 FREE_AND_NULL(tok1);
172                 FREE_AND_NULL(tok2);
173                 sscanf(buf, "%ms %ms", &tok1, &tok2);
174                 if (tok1 && strcasecmp(TAG_LOADER, tok1) == 0) {
175                         if (cur_info != NULL) {
176                                 __flush_extra_array(cur_info->extra, key,
177                                                 extra_array);
178                                 extra_array = NULL;
179                                 key = NULL;
180                                 list = g_list_append(list, cur_info);
181                         }
182                         cur_info = __create_loader_info();
183                         continue;
184                 }
185
186                 if (!tok1 || !tok2)
187                         continue;
188                 if (tok1[0] == '\0' || tok2[0] == '\0' || tok1[0] == '#')
189                         continue;
190
191                 if (strcasecmp(TAG_NAME, tok1) == 0) {
192                         cur_info->name = strdup(tok2);
193                 } else if (strcasecmp(TAG_EXE, tok1) == 0) {
194                         cur_info->exe = strdup(tok2);
195                 } else if (strcasecmp(TAG_APP_TYPE, tok1) == 0) {
196                         __parse_app_types(cur_info, &buf[strlen(tok1)]);
197                 } else if (strcasecmp(TAG_DETECTION_METHOD, tok1) == 0) {
198                         __parse_detection_method(cur_info, &buf[strlen(tok1)]);
199                 } else if (strcasecmp(TAG_TIMEOUT, tok1) == 0) {
200                         cur_info->timeout_val = atoi(tok2);
201                 } else if (strcasecmp(TAG_EXTRA, tok1) == 0) {
202                         __parse_extra(cur_info, buf);
203                 } else if (strcasecmp(TAG_EXTRA_ARRAY, tok1) == 0) {
204                         __flush_extra_array(cur_info->extra, key, extra_array);
205                         extra_array = NULL;
206                         key = strdup(tok2);
207                 } else if (strcasecmp(TAG_EXTRA_ARRAY_VAL, tok1) == 0) {
208                         extra_array = g_list_append(extra_array, strdup(tok2));
209                 } else if (strcasecmp(TAG_HW_ACC, tok1) == 0) {
210                         cur_info->hw_acc = strdup(tok2);
211                 } else if (strcasecmp(TAG_ALTERNATIVE_LOADER, tok1) == 0) {
212                         cur_info->alternative_loaders =
213                                 g_list_append(cur_info->alternative_loaders,
214                                                 strdup(tok2));
215                 }
216         }
217
218         if (cur_info != NULL) {
219                 __flush_extra_array(cur_info->extra, key, extra_array);
220                 list = g_list_append(list, cur_info);
221         }
222
223         if (tok1)
224                 free(tok1);
225         if (tok2)
226                 free(tok2);
227
228         fclose(fp);
229
230         return list;
231 }
232
233 GList *_loader_info_load(const char *path)
234 {
235         DIR *dir_info;
236         struct dirent *entry = NULL;
237         GList *list = NULL;
238         char buf[PATH_MAX];
239         char *ext;
240
241         dir_info = opendir(path);
242         if (dir_info == NULL)
243                 return  NULL;
244
245         while ((entry = readdir(dir_info)) != NULL) {
246                 if (entry->d_name[0] == '.')
247                         continue;
248                 ext = strrchr(entry->d_name, '.');
249                 if (ext && !strcmp(ext, ".loader")) {
250                         snprintf(buf, sizeof(buf), "%s/%s", path, entry->d_name);
251                         list = __parse_file(list, buf);
252                 }
253         }
254         closedir(dir_info);
255
256         return list;
257 }
258
259 static void __free_info(gpointer data)
260 {
261         loader_info_t *info;
262
263         if (data == NULL)
264                 return;
265
266         info = (loader_info_t *)data;
267
268         free(info->name);
269         free(info->exe);
270         if (info->app_types)
271                 g_list_free_full(info->app_types, free);
272         free(info->hw_acc);
273         if (info->extra)
274                 bundle_free(info->extra);
275         if (info->alternative_loaders)
276                 g_list_free_full(info->alternative_loaders, free);
277
278         free(info);
279 }
280
281 void _loader_info_dispose(GList *info)
282 {
283         g_list_free_full(info, __free_info);
284 }
285
286 static int __comp_str(gconstpointer a, gconstpointer b)
287 {
288         if (!a || !b)
289                 return -1;
290         return strcmp(a, b);
291 }
292
293 static int __comp_app_type_with_hw_acc(gconstpointer a, gconstpointer b)
294 {
295         loader_info_t *info = (loader_info_t *)a;
296
297         if (info == NULL || info->app_types == NULL || b == NULL)
298                 return -1;
299
300         if (g_list_find_custom(info->app_types, b, __comp_str) &&
301                 (info->hw_acc == NULL || !strcasecmp(VAL_ON, info->hw_acc)))
302                 return 0;
303
304         return -1;
305 }
306
307 static int __comp_app_type_with_sw_acc(gconstpointer a, gconstpointer b)
308 {
309         loader_info_t *info = (loader_info_t *)a;
310
311         if (info == NULL || info->app_types == NULL || b == NULL)
312                 return -1;
313
314         if (g_list_find_custom(info->app_types, b, __comp_str) &&
315                 (info->hw_acc == NULL || !strcasecmp(VAL_OFF, info->hw_acc)))
316                 return 0;
317
318         return -1;
319 }
320
321 static int __comp_name(gconstpointer a, gconstpointer b)
322 {
323         loader_info_t *info = (loader_info_t *)a;
324
325         if (info == NULL || info->name == NULL || b == NULL)
326                 return -1;
327
328         return strcmp(info->name, b);
329 }
330
331 int _loader_info_find_type(GList *info,  const char *app_type, bool hwacc)
332 {
333         GList *cur;
334
335         if (hwacc) {
336                 cur = g_list_find_custom(info, app_type,
337                                 __comp_app_type_with_hw_acc);
338         } else {
339                 cur = g_list_find_custom(info, app_type,
340                                 __comp_app_type_with_sw_acc);
341         }
342
343         if (cur == NULL)
344                 return -1;
345
346         loader_info_t *cur_info = (loader_info_t *)cur->data;
347
348         return cur_info->type;
349 }
350
351 int _loader_info_find_type_by_loader_name(GList *info,  const char *loader_name)
352 {
353         GList *cur = NULL;
354
355         cur = g_list_find_custom(info, loader_name, __comp_name);
356         if (cur == NULL)
357                 return -1;
358
359         loader_info_t *cur_info = (loader_info_t *)cur->data;
360
361         return cur_info->type;
362 }
363
364 static int *__make_type_array(GList *info, GList *loaders, int *len)
365 {
366         int l;
367         int *t;
368         loader_info_t *i;
369         GList *c;
370         GList *cur;
371         int j = 0;
372
373         l = g_list_length(loaders);
374
375         if (l <= 0)
376                 return NULL;
377
378         t = malloc(sizeof(int) * l);
379         if (!t)
380                 return NULL;
381
382         *len = l;
383
384         cur = loaders;
385         while (cur) {
386                 c = g_list_find_custom(info, cur->data, __comp_name);
387
388                 if (c) {
389                         i = (loader_info_t *)c->data;
390                         t[j] = i->type;
391                         j++;
392                 }
393
394                 cur = g_list_next(cur);
395         }
396
397         return t;
398 }
399
400 int *_loader_get_alternative_types(GList *info, int type, int *len)
401 {
402         GList *cur;
403         loader_info_t *i;
404
405         if (!info)
406                 return NULL;
407
408         cur = info;
409         while (cur) {
410                 i = (loader_info_t *)cur->data;
411                 if (i->type == type) {
412                         if (!i->alternative_loaders)
413                                 return NULL;
414
415                         return __make_type_array(info, i->alternative_loaders,
416                                         len);
417                 }
418                 cur = g_list_next(cur);
419         }
420
421         return NULL;
422 }
423
424
425