Fix directory hierarchy & cmake configuration files
[platform/core/appfw/launchpad.git] / src / launchpad-process-pool / 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_ACTIVATION_METHOD           "ACTIVATION_METHOD"
33 #define TAG_DEACTIVATION_METHOD         "DEACTIVATION_METHOD"
34 #define TAG_TTL                         "TTL"
35 #define TAG_TIMEOUT                     "TIMEOUT"
36 #define TAG_EXTRA                       "EXTRA"
37 #define TAG_EXTRA_ARRAY                 "EXTRA_ARRAY"
38 #define TAG_EXTRA_ARRAY_VAL             "EXTRA_ARRAY_VAL"
39 #define TAG_ALTERNATIVE_LOADER          "ALTERNATIVE_LOADER"
40 #define TAG_HW_ACC                      "HW_ACC"
41 #define TAG_CPU_THRESHOLD_MAX           "CPU_THRESHOLD_MAX"
42 #define TAG_CPU_THRESHOLD_MIN           "CPU_THRESHOLD_MIN"
43 #define TAG_ON_BOOT                     "ON_BOOT"
44 #define TAG_HYDRA                       "HYDRA"
45 #define TAG_APP_CHECK                   "APP_CHECK"
46
47 #define VAL_ON                          "ON"
48 #define VAL_OFF                         "OFF"
49 #define VAL_METHOD_TIMEOUT              "TIMEOUT"
50 #define VAL_METHOD_DEMAND               "DEMAND"
51 #define VAL_METHOD_VISIBILITY           "VISIBILITY"
52 #define VAL_METHOD_REQUEST              "REQUEST"
53 #define VAL_METHOD_AVAILABLE_MEMORY     "AVAILABLE_MEMORY"
54 #define VAL_METHOD_TTL                  "TTL"
55 #define VAL_METHOD_OUT_OF_MEMORY        "OUT_OF_MEMORY"
56
57 static int __comp_name(gconstpointer a, gconstpointer b);
58 static void __free_info(gpointer data);
59
60 static loader_info_t *__create_loader_info()
61 {
62         loader_info_t *info;
63
64         info = malloc(sizeof(loader_info_t));
65         if (info == NULL) {
66                 _E("Out of memory");
67                 return NULL;
68         }
69
70         info->type = 0;
71         info->name = NULL;
72         info->exe = NULL;
73         info->app_types = NULL;
74         info->hw_acc = NULL;
75         info->alternative_loaders = NULL;
76         info->detection_method = METHOD_TIMEOUT | METHOD_VISIBILITY |
77                 METHOD_INSTALL;
78         info->timeout_val = 5000;
79         info->extra = bundle_create();
80         info->cpu_threshold_max = DEFAULT_CPU_THRESHOLD_MAX;
81         info->cpu_threshold_min = DEFAULT_CPU_THRESHOLD_MIN;
82         info->on_boot = true;
83         info->app_exists = false;
84         info->activation_method = 0;
85         info->deactivation_method = 0;
86         info->ttl = 600; /* 10 minutes */
87         info->is_hydra = false;
88         info->app_check = true;
89
90         return info;
91 }
92
93 static void __parse_detection_method(loader_info_t *info, char *line)
94 {
95         char *token;
96         char *savedptr;
97
98         token = strtok_r(line, " |\t\r\n", &savedptr);
99         info->detection_method = 0;
100         while (token) {
101                 if (!strcmp(token, VAL_METHOD_TIMEOUT))
102                         info->detection_method |= METHOD_TIMEOUT;
103                 else if (!strcmp(token, VAL_METHOD_VISIBILITY))
104                         info->detection_method |= METHOD_VISIBILITY;
105                 else if (!strcmp(token, VAL_METHOD_DEMAND))
106                         info->detection_method |= METHOD_DEMAND;
107
108                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
109         }
110
111         info->detection_method |= METHOD_INSTALL;
112         _D("detection_method:%d", info->detection_method);
113 }
114
115 static void __parse_activation_method(loader_info_t *info, char *line)
116 {
117         char *token;
118         char *savedptr;
119
120         token = strtok_r(line, " |\t\r\n", &savedptr);
121         info->activation_method = 0;
122         while (token) {
123                 if (!strcmp(token, VAL_METHOD_REQUEST))
124                         info->activation_method |= METHOD_REQUEST;
125                 else if (!strcmp(token, VAL_METHOD_AVAILABLE_MEMORY))
126                         info->activation_method |= METHOD_AVAILABLE_MEMORY;
127
128                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
129         }
130
131         _D("activation_method:%d", info->activation_method);
132 }
133
134 static void __parse_deactivation_method(loader_info_t *info, char *line)
135 {
136         char *token;
137         char *savedptr;
138
139         token = strtok_r(line, " |\t\r\n", &savedptr);
140         info->deactivation_method = 0;
141         while (token) {
142                 if (!strcmp(token, VAL_METHOD_TTL))
143                         info->deactivation_method |= METHOD_TTL;
144                 else if (!strcmp(token, VAL_METHOD_OUT_OF_MEMORY))
145                         info->deactivation_method |= METHOD_OUT_OF_MEMORY;
146
147                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
148         }
149
150         _D("deactivation_method:%d", info->deactivation_method);
151 }
152
153 static void __parse_app_types(loader_info_t *info, char *line)
154 {
155         char *token;
156         char *savedptr;
157
158         token = strtok_r(line, " |\t\r\n", &savedptr);
159         while (token) {
160                 info->app_types = g_list_append(info->app_types, strdup(token));
161                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
162         }
163 }
164
165 static void __parse_extra(loader_info_t *info, char *line)
166 {
167         char *tok1 = NULL;
168         char *tok2 = NULL;
169         char *tok3 = NULL;
170
171         if (info->extra == NULL)
172                 return;
173
174         sscanf(line, "%ms %ms %ms", &tok1, &tok2, &tok3);
175
176         if (!tok1 || !tok2 || !tok3)
177                 goto end;
178
179         if (strlen(tok2) == 0 || strlen(tok3) == 0)
180                 goto end;
181
182         bundle_add_str(info->extra, tok2, tok3);
183
184 end:
185         if (tok1)
186                 free(tok1);
187         if (tok2)
188                 free(tok2);
189         if (tok3)
190                 free(tok3);
191 }
192
193 static void __add_extra_array_from_list(bundle *b, const char *key, GList *list)
194 {
195         const char **array;
196         int len;
197         int i;
198         GList *cur;
199
200         if (b == NULL || key == NULL || list == NULL)
201                 return;
202
203         len = g_list_length(list);
204         array = malloc(sizeof(const char *) * len);
205         if (array == NULL)
206                 return;
207
208         cur = list;
209         for (i = 0; i < len; i++) {
210                 array[i] = cur->data;
211                 cur = g_list_next(cur);
212         }
213
214         bundle_add_str_array(b, key, array, len);
215         free(array);
216 }
217
218 static void __flush_extra_array(bundle *b, char *key, GList *list)
219 {
220         if (list) {
221                 __add_extra_array_from_list(b, key, list);
222                 g_list_free_full(list, free);
223         }
224
225         free(key);
226 }
227
228 static GList *__parse_file(GList *list, const char *path)
229 {
230         FILE *fp;
231         char buf[LINE_MAX];
232         char *tok1 = NULL;
233         char *tok2 = NULL;
234         loader_info_t *cur_info = NULL;
235         char *key = NULL;
236         GList *extra_array = NULL;
237
238         fp = fopen(path, "rt");
239         if (fp == NULL)
240                 return list;
241
242         while (fgets(buf, sizeof(buf), fp) != NULL) {
243                 FREE_AND_NULL(tok1);
244                 FREE_AND_NULL(tok2);
245                 sscanf(buf, "%ms %ms", &tok1, &tok2);
246                 if (tok1 && strcasecmp(TAG_LOADER, tok1) == 0) {
247                         if (cur_info != NULL) {
248                                 __flush_extra_array(cur_info->extra, key,
249                                                 extra_array);
250                                 extra_array = NULL;
251                                 key = NULL;
252                                 list = g_list_append(list, cur_info);
253                         }
254                         cur_info = __create_loader_info();
255                         if (!cur_info)
256                                 break;
257                         continue;
258                 }
259
260                 if (!tok1 || !tok2 || !cur_info)
261                         continue;
262                 if (tok1[0] == '\0' || tok2[0] == '\0' || tok1[0] == '#')
263                         continue;
264
265                 if (strcasecmp(TAG_NAME, tok1) == 0) {
266                         cur_info->name = strdup(tok2);
267                 } else if (strcasecmp(TAG_EXE, tok1) == 0) {
268                         cur_info->exe = strdup(tok2);
269                 } else if (strcasecmp(TAG_APP_TYPE, tok1) == 0) {
270                         __parse_app_types(cur_info, &buf[strlen(tok1)]);
271                 } else if (strcasecmp(TAG_DETECTION_METHOD, tok1) == 0) {
272                         __parse_detection_method(cur_info, &buf[strlen(tok1)]);
273                 } else if (strcasecmp(TAG_ACTIVATION_METHOD, tok1) == 0) {
274                         __parse_activation_method(cur_info,
275                                         &buf[strlen(tok1)]);
276                 } else if (strcasecmp(TAG_DEACTIVATION_METHOD, tok1) == 0) {
277                         __parse_deactivation_method(cur_info,
278                                         &buf[strlen(tok1)]);
279                 } else if (strcasecmp(TAG_TTL, tok1) == 0) {
280                         cur_info->ttl = strtoul(tok2, NULL, 10);
281                 } else if (strcasecmp(TAG_TIMEOUT, tok1) == 0) {
282                         cur_info->timeout_val = atoi(tok2);
283                 } else if (strcasecmp(TAG_EXTRA, tok1) == 0) {
284                         __parse_extra(cur_info, buf);
285                 } else if (strcasecmp(TAG_EXTRA_ARRAY, tok1) == 0) {
286                         __flush_extra_array(cur_info->extra, key, extra_array);
287                         extra_array = NULL;
288                         key = strdup(tok2);
289                 } else if (strcasecmp(TAG_EXTRA_ARRAY_VAL, tok1) == 0) {
290                         extra_array = g_list_append(extra_array, strdup(tok2));
291                 } else if (strcasecmp(TAG_HW_ACC, tok1) == 0) {
292                         cur_info->hw_acc = strdup(tok2);
293                 } else if (strcasecmp(TAG_ALTERNATIVE_LOADER, tok1) == 0) {
294                         cur_info->alternative_loaders =
295                                 g_list_append(cur_info->alternative_loaders,
296                                                 strdup(tok2));
297                 } else if (strcasecmp(TAG_CPU_THRESHOLD_MAX, tok1) == 0) {
298                         cur_info->cpu_threshold_max = atoi(tok2);
299                 } else if (strcasecmp(TAG_CPU_THRESHOLD_MIN, tok1) == 0) {
300                         cur_info->cpu_threshold_min = atoi(tok2);
301                 } else if (strcasecmp(TAG_ON_BOOT, tok1) == 0) {
302                         if (tok2 && strcasecmp(VAL_OFF, tok2) == 0)
303                                 cur_info->on_boot = false;
304                 } else if (strcasecmp(TAG_HYDRA, tok1) == 0) {
305                         if (strcasecmp(VAL_ON, tok2) == 0) {
306                                 cur_info->is_hydra = 1;
307                         } else {
308                                 cur_info->is_hydra = 0;
309                         }
310                 } else if (strcasecmp(TAG_APP_CHECK, tok1) == 0) {
311                         if (tok2 && strcasecmp(VAL_OFF, tok2) == 0)
312                                 cur_info->app_check = false;
313                 }
314         }
315
316         if (cur_info != NULL) {
317                 __flush_extra_array(cur_info->extra, key, extra_array);
318                 list = g_list_append(list, cur_info);
319         }
320
321         if (tok1)
322                 free(tok1);
323         if (tok2)
324                 free(tok2);
325
326         fclose(fp);
327
328         return list;
329 }
330
331 GList *_loader_info_load_dir(const char *path)
332 {
333         DIR *dir_info;
334         struct dirent *entry = NULL;
335         GList *list = NULL;
336         char buf[PATH_MAX];
337         char *ext;
338
339         dir_info = opendir(path);
340         if (dir_info == NULL)
341                 return  NULL;
342
343         while ((entry = readdir(dir_info)) != NULL) {
344                 if (entry->d_name[0] == '.')
345                         continue;
346                 ext = strrchr(entry->d_name, '.');
347                 if (ext && !strcmp(ext, ".loader")) {
348                         snprintf(buf, sizeof(buf), "%s/%s", path, entry->d_name);
349                         list = __parse_file(list, buf);
350                 }
351         }
352         closedir(dir_info);
353
354         return list;
355 }
356
357 GList *_loader_info_load_file(GList *list, const char *path)
358 {
359         return __parse_file(list, path);
360 }
361
362 GList *_loader_info_unload(GList *list, const char *loader_name)
363 {
364         GList *cur;
365         loader_info_t *info;
366
367         cur = g_list_find_custom(list, loader_name, __comp_name);
368         if (cur == NULL)
369                 return list;
370
371         info = cur->data;
372
373         list = g_list_remove(list, info);
374         __free_info(info);
375
376         return list;
377 }
378
379 const char* _loader_info_find_loader_path_by_loader_name(GList *list, const char *loader_name)
380 {
381         GList *cur;
382         loader_info_t *info;
383
384         cur = g_list_find_custom(list, loader_name, __comp_name);
385         if (cur == NULL)
386                 return NULL;
387
388         info = cur->data;
389
390         return info->exe;
391 }
392
393 loader_info_t* _loader_info_find_loader_by_loader_name(GList *list, const char *loader_name)
394 {
395         GList *cur;
396         loader_info_t *info;
397
398         cur = g_list_find_custom(list, loader_name, __comp_name);
399         if (cur == NULL)
400                 return NULL;
401
402         info = cur->data;
403
404         return info;
405 }
406
407 static void __free_info(gpointer data)
408 {
409         loader_info_t *info;
410
411         if (data == NULL)
412                 return;
413
414         info = (loader_info_t *)data;
415
416         free(info->name);
417         free(info->exe);
418         if (info->app_types)
419                 g_list_free_full(info->app_types, free);
420         free(info->hw_acc);
421         if (info->extra)
422                 bundle_free(info->extra);
423         if (info->alternative_loaders)
424                 g_list_free_full(info->alternative_loaders, free);
425
426         free(info);
427 }
428
429 void _loader_info_dispose(GList *info)
430 {
431         g_list_free_full(info, __free_info);
432 }
433
434 static int __comp_str(gconstpointer a, gconstpointer b)
435 {
436         if (!a || !b)
437                 return -1;
438         return strcmp(a, b);
439 }
440
441 static int __comp_app_type_with_hw_acc(gconstpointer a, gconstpointer b)
442 {
443         loader_info_t *info = (loader_info_t *)a;
444
445         if (info == NULL || info->app_types == NULL || b == NULL)
446                 return -1;
447
448         if (g_list_find_custom(info->app_types, b, __comp_str) &&
449                 (info->hw_acc == NULL || !strcasecmp(VAL_ON, info->hw_acc)))
450                 return 0;
451
452         return -1;
453 }
454
455 static int __comp_app_type_with_sw_acc(gconstpointer a, gconstpointer b)
456 {
457         loader_info_t *info = (loader_info_t *)a;
458
459         if (info == NULL || info->app_types == NULL || b == NULL)
460                 return -1;
461
462         if (g_list_find_custom(info->app_types, b, __comp_str) &&
463                 (info->hw_acc == NULL || !strcasecmp(VAL_OFF, info->hw_acc)))
464                 return 0;
465
466         return -1;
467 }
468
469 static int __comp_name(gconstpointer a, gconstpointer b)
470 {
471         loader_info_t *info = (loader_info_t *)a;
472
473         if (info == NULL || info->name == NULL || b == NULL)
474                 return -1;
475
476         return strcmp(info->name, b);
477 }
478
479 int _loader_info_find_type(GList *info,  const char *app_type, bool hwacc)
480 {
481         GList *cur;
482
483         if (hwacc) {
484                 cur = g_list_find_custom(info, app_type,
485                                 __comp_app_type_with_hw_acc);
486         } else {
487                 cur = g_list_find_custom(info, app_type,
488                                 __comp_app_type_with_sw_acc);
489         }
490
491         if (cur == NULL)
492                 return -1;
493
494         loader_info_t *cur_info = (loader_info_t *)cur->data;
495
496         return cur_info->type;
497 }
498
499 int _loader_info_find_type_by_loader_name(GList *info,  const char *loader_name)
500 {
501         GList *cur = NULL;
502
503         cur = g_list_find_custom(info, loader_name, __comp_name);
504         if (cur == NULL)
505                 return -1;
506
507         loader_info_t *cur_info = (loader_info_t *)cur->data;
508
509         return cur_info->type;
510 }
511
512 static int *__make_type_array(GList *info, GList *loaders, int *len)
513 {
514         int l;
515         int *t;
516         loader_info_t *i;
517         GList *c;
518         GList *cur;
519         int j = 0;
520
521         l = g_list_length(loaders);
522
523         if (l <= 0)
524                 return NULL;
525
526         t = malloc(sizeof(int) * l);
527         if (!t)
528                 return NULL;
529
530         *len = l;
531
532         cur = loaders;
533         while (cur) {
534                 c = g_list_find_custom(info, cur->data, __comp_name);
535
536                 if (c) {
537                         i = (loader_info_t *)c->data;
538                         t[j] = i->type;
539                         j++;
540                 }
541
542                 cur = g_list_next(cur);
543         }
544
545         return t;
546 }
547
548 int *_loader_get_alternative_types(GList *info, int type, int *len)
549 {
550         GList *cur;
551         loader_info_t *i;
552
553         if (!info)
554                 return NULL;
555
556         cur = info;
557         while (cur) {
558                 i = (loader_info_t *)cur->data;
559                 if (i->type == type) {
560                         if (!i->alternative_loaders)
561                                 return NULL;
562
563                         return __make_type_array(info, i->alternative_loaders,
564                                         len);
565                 }
566                 cur = g_list_next(cur);
567         }
568
569         return NULL;
570 }
571
572 int _loader_info_foreach(GList *info, loader_info_foreach_cb callback,
573                 void *data)
574 {
575         GList *cur;
576         loader_info_t *i;
577
578         if (!info || !callback)
579                 return -1;
580
581         cur = info;
582         while (cur) {
583                 i = (loader_info_t *)cur->data;
584                 callback(i, data);
585                 cur = g_list_next(cur);
586         }
587
588         return 0;
589 }
590
591 bool _loader_info_exist_app_type(loader_info_t *info, const char *app_type)
592 {
593         GList *list;
594
595         list = g_list_find_custom(info->app_types, app_type, __comp_str);
596         if (list)
597                 return true;
598
599         return false;
600 }