[FEATURE] Implement kernel -> user connection
[platform/core/system/swap-manager.git] / daemon / utils.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12  * Nikita Kalyazin    <n.kalyazin@samsung.com>
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * - Samsung RnD Institute Russia
29  *
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <errno.h>
36
37 #include <signal.h>                     // for signal
38 #include <pthread.h>
39 #include <unistd.h>             // for unlink
40 #include <dirent.h>             // for opendir, readdir
41 #include <sys/types.h>  // for open
42 #include <sys/stat.h>   // for open
43 #include <fcntl.h>              // for open
44 #include <grp.h>                // for setgroups
45 #include <sys/wait.h> /* waitpid */
46
47 #include "daemon.h"
48 #include "utils.h"
49 #include "smack.h"
50 #include "debug.h"
51
52 #define BUFFER_MAX                      1024
53 #define SID_APP                         5000
54 #define MANIFEST_PATH           "/info/manifest.xml"
55
56 #define APPDIR1                         "/opt/apps/"
57 #define APPDIR2                         "/opt/usr/apps/"
58
59 uint64_t str_to_uint64(char* str)
60 {
61         uint64_t res = 0;
62
63         if(str != NULL)
64         {
65                 while(*str >= '0' && *str <= '9')
66                 {
67                         res = res * 10 + (*str - '0');
68                         str++;
69                 }
70         }
71
72         return res;
73 }
74
75 int64_t str_to_int64(char* str)
76 {
77         int64_t res = 0;
78         int64_t factor = 1;
79
80         if(str != NULL)
81         {
82                 if(*str == '-')
83                 {
84                         factor = -1;
85                         str++;
86                 }
87                 else if(*str == '+')
88                 {
89                         factor = 1;
90                         str++;
91                 }
92
93                 while(*str >= '0' && *str <= '9')
94                 {
95                         res = res * 10 + (*str - '0');
96                         str++;
97                 }
98         }
99
100         return (res * factor);
101 }
102
103 // return 0 if succeed
104 // return -1 if error occured
105 int remove_indir(const char *dirname)
106 {
107         DIR *dir;
108         struct dirent *entry;
109         char path[PATH_MAX];
110
111         dir = opendir(dirname);
112         if(dir == NULL)
113         {
114                 return -1;
115         }
116
117         while((entry = readdir(dir)) != NULL)
118         {
119                 if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
120                 {
121                         snprintf(path, (size_t) PATH_MAX, "%s/%s", dirname, entry->d_name);
122                         if (entry->d_type != DT_DIR)    // file
123                         {
124                                 unlink(path);
125                         }
126                         else { }        // directory
127                 }
128         }
129         closedir(dir);
130
131         return 0;
132 }
133
134 /* execute applcation with executable binary path */
135 int exec_app_tizen(const char *app_id, const char *exec_path)
136 {
137         pid_t pid;
138
139         LOGI("exec %s\n", exec_path);
140
141         if (exec_path == NULL || !strlen(exec_path)) {
142                 LOGE("Executable path is not correct\n");
143                 return -1;
144         }
145         LOGI("launch app path is %s, executable path is %s\n"
146              "launch app name (%s), app_id (%s)\n",
147              LAUNCH_APP_PATH, exec_path, LAUNCH_APP_NAME, app_id);
148         pid = fork();
149         if (pid == -1)
150                 return -1;
151
152         if (pid > 0) { /* parent */
153                 int status, ret;
154                 do
155                         ret = waitpid(pid, &status, 0);
156                 while (ret == -1 && errno == EINTR);
157                 return 0;
158         } else { /* child */
159                 execl(LAUNCH_APP_PATH, LAUNCH_APP_NAME, app_id, LAUNCH_APP_SDK,
160                       DA_PRELOAD_EXEC, NULL);
161                 /* FIXME: If code flows here, it deserves greater attention */
162                 _Exit(EXIT_FAILURE);
163         }
164 }
165
166 int exec_app_common(const char* exec_path)
167 {
168         pid_t pid;
169         char command[PATH_MAX];
170
171         LOGI("exec %s\n", exec_path);
172         if (exec_path == NULL || !strlen(exec_path)) {
173                 LOGE("Executable path is not correct\n");
174                 return -1;
175         }
176
177         sprintf(command, "%s %s", DA_PRELOAD_OSP, exec_path);
178         LOGI("cmd: %s\n", command);
179
180         pid = fork();
181         if (pid == -1)
182                 return -1;
183
184         if (pid > 0) { /* parent */
185                 return 0;
186         } else { /* child */
187                 execl(SHELL_CMD, SHELL_CMD, "-c", command, NULL);
188                 /* FIXME: Again, such case deserve much more attention */
189                 _Exit(EXIT_FAILURE);
190         }
191 }
192
193 // find process id from executable binary path
194 pid_t find_pid_from_path(const char* path)
195 {
196         pid_t status = 0;
197
198         char buffer[BUFFER_MAX] = {0};
199         char command[BUFFER_MAX] = {0};
200
201         sprintf(command, "/bin/pidof %s", path);
202         LOGI("look for <%s>\n", path);
203
204         FILE *fp = popen(command, "r");
205         if (!fp)
206                 return status;
207
208         while (fgets(buffer, BUFFER_MAX, fp) != NULL)
209                 LOGI("result of 'pidof' is %s\n", buffer);
210
211         pclose(fp);
212
213         if (strlen(buffer) > 0) {
214                 if (sscanf(buffer, "%d\n", &status) != 1) {
215                         LOGW("Failed to read result buffer of 'pidof',"
216                              " status(%d) with cmd '%s'\n", status, command);
217                         return 0;
218                 }
219         }
220
221         return status;
222 }
223
224 static pid_t get_pid_by_path(const char *binary_path)
225 {
226         pid_t pkg_pid;
227         int len;
228         char *real_path;
229         static const char exe_line[] = ".exe";
230
231
232         pkg_pid = find_pid_from_path(binary_path);
233         if (pkg_pid == 0) {
234                 len = strlen(binary_path);
235                 real_path = malloc(len + sizeof(exe_line));
236                 if (real_path == NULL) {
237                         LOGE("cannot alloc memory\n");
238                         return -1;
239                 }
240                 memcpy(real_path, binary_path, len + 1);
241
242                 // try remove or add ".exe" and get pid
243                 if (strcmp(real_path + len - (sizeof(exe_line) - 1), exe_line) == 0)
244                         // remove .exe from tPath
245                         real_path[len - (sizeof(exe_line) - 1)] = '\0';
246                 else
247                         // add .exe
248                         memcpy(&real_path[len], exe_line, sizeof(exe_line));
249
250                 pkg_pid = find_pid_from_path(real_path);
251                 free(real_path);
252         }
253
254         return pkg_pid;
255 }
256
257 static int find_alternative_bin_path(const char *binary_path, char *alter_bin_path) {
258         // alternative path may be /opt/apps/... or /opt/usr/apps/...)
259         if (strncmp(binary_path, APPDIR1, strlen(APPDIR1)) == 0) {
260                 strcpy(alter_bin_path, APPDIR2);
261                 strcat(alter_bin_path, binary_path + strlen(APPDIR1));
262         } else if (strncmp(binary_path, APPDIR2, strlen(APPDIR2)) == 0) {
263                 strcpy(alter_bin_path, APPDIR1);
264                 strcat(alter_bin_path, binary_path + strlen(APPDIR2));
265         } else {
266                 return 1;
267         }
268         return 0;
269 }
270
271 int kill_app(const char *binary_path)
272 {
273         pid_t pkg_pid;
274         char alter_bin_path[PATH_MAX];
275
276         LOGI("kill %s (%d)\n", binary_path, SIGKILL);
277
278         pkg_pid = get_pid_by_path(binary_path);
279
280         if (pkg_pid == 0) {
281                 if (find_alternative_bin_path(binary_path, alter_bin_path) == 0)
282                         pkg_pid = get_pid_by_path(alter_bin_path);
283         }
284
285         if (pkg_pid != 0) {
286                 if (kill(pkg_pid, SIGTERM) == -1) {
287                         LOGE("cannot kill %d -%d err<%s>\n", pkg_pid, SIGKILL,
288                              strerror(errno));
289                         return -1;
290                 } else {
291                         // we need sleep up there because kill() function
292                         // returns control immediately after send signal
293                         // without it app_launch returns err on start app
294                         sleep(1);
295                         LOGI("killed %d -%d\n", pkg_pid, SIGKILL);
296                 }
297         } else
298                 LOGI("cannot kill <%s>; process not found\n", binary_path);
299
300         return 0;
301 }
302
303 int get_executable(char* appPath, char* buf, int buflen)
304 {
305         int fd;
306
307         sprintf(buf, "%s.exe", appPath);
308         fd = open(buf, O_RDONLY);
309         if(fd != -1)
310         {
311                 close(fd);
312         }
313         else
314         {
315                 strcpy(buf, appPath);
316         }
317         return 0;
318 }
319
320 int get_app_install_path(char *strAppInstall, int length)
321 {
322         FILE *fp;
323         char buf[BUFFER_MAX];
324         char *p;
325         int i;
326
327         if ((fp = fopen(DA_INSTALL_PATH, "r")) == NULL)
328         {
329                 LOGE("Failed to open %s\n", DA_INSTALL_PATH);
330                 return -1;
331         }
332
333         /*ex : <15>   DW_AT_comp_dir    : (indirect string, offset: 0x25f): /home/yt/workspace/templatetest/Debug-Tizen-Emulator        */
334         while (fgets(buf, BUFFER_MAX, fp) != NULL)
335         {
336                 //name
337                 p = buf;
338                 for (i = 0; i < BUFFER_MAX; i++)
339                 {
340                         if (*p == ':')
341                                 break;
342                         p++;
343                 }
344
345                 if (*p != ':')
346                         break;
347                 else
348                         p++;
349
350                 //(...,offset:...)
351                 for (; i < BUFFER_MAX; i++)
352                 {
353                         if (*p == '(')
354                         {
355                                 while (*p != ')')
356                                 {
357                                         p++;
358                                 }
359                         }
360                         if (*p == ':')
361                                 break;
362                         p++;
363                 }
364
365                 //find
366                 if (*p != ':')
367                         break;
368                 for (; i < BUFFER_MAX - 1; i++)
369                 {
370                         if (*p == ':' || *p == ' ' || *p == '\t')
371                                 p++;
372                         else
373                                 break;
374                 }
375
376                 //name
377                 if (strlen(p) <= length)
378                 {
379                         sprintf(strAppInstall, "%s", p);
380                         for (i = 0; i < strlen(p); i++)
381                         {
382                                 if (strAppInstall[i] == '\n' || strAppInstall[i] == '\t')
383                                 {
384                                         strAppInstall[i] = '\0';
385                                         break;
386                                 }
387                         }
388                         fclose(fp);
389                         return 1;
390                 }
391         }
392         fclose(fp);
393         return -1;
394 }
395
396 int is_app_built_pie(void)
397 {
398         int result;
399         FILE *fp;
400         char buf[BUFFER_MAX];
401
402         if((fp = fopen(DA_BUILD_OPTION, "r")) == NULL)
403         {
404                 LOGE("Failed to open %s\n", DA_BUILD_OPTION);
405                 return -1;
406         }
407
408         if(fgets(buf, BUFFER_MAX, fp) != NULL)
409         {
410                 if(strcmp(buf, "DYN\n") == 0)
411                         result = 1;
412                 else if(strcmp(buf, "EXEC\n") == 0)
413                         result = 0;
414                 else
415                         result = -1;
416         }
417         else
418         {
419                 result = -1;
420         }
421         fclose(fp);
422
423         return result;
424 }
425
426 int get_app_base_address(int *baseAddress)
427 {
428         int res;
429         FILE *fp;
430         char buf[BUFFER_MAX];
431
432         if((fp = fopen(DA_BASE_ADDRESS, "r")) == NULL)
433         {
434                 LOGE("Failed to open %s\n", DA_BASE_ADDRESS);
435                 return -1;
436         }
437
438         if(fgets(buf, BUFFER_MAX, fp) != NULL)
439         {
440                 res = sscanf(buf, "%x", baseAddress);
441         }
442         else
443         {
444                 res = -1;
445         }
446         fclose(fp);
447
448         return res;
449 }
450
451 int is_same_app_process(char* appPath, int pid)
452 {
453         int ret = 0;
454         int tlen;
455         FILE *fp;
456         char buf[BUFFER_MAX];
457         char cmdPath[PATH_MAX];
458         char tPath[PATH_MAX];
459         char buf_res[PATH_MAX];
460         char tPath_res[PATH_MAX];
461
462         strcpy(tPath, appPath);
463         tlen = strlen(tPath);
464         if(strcmp(tPath + tlen - 4, ".exe") == 0)
465         {
466                 // remove .exe from tPath
467                 tPath[tlen - 4] = '\0';
468         }
469
470         sprintf(cmdPath, "/proc/%d/cmdline", pid);
471
472         if((fp = fopen(cmdPath, "r")) == NULL)
473         {
474                 return 0;
475         }
476
477         if(fgets(buf, BUFFER_MAX, fp) != NULL)
478         {
479                 tlen = strlen(buf);
480                 if(strcmp(buf + tlen - 4, ".exe") == 0)
481                 {
482                         // remove .exe from tPath
483                         buf[tlen - 4] = '\0';
484                 }
485
486                 dereference_tizen_exe_path(buf, buf_res);
487                 dereference_tizen_exe_path(tPath, tPath_res);
488
489                 if(strcmp(buf_res, tPath_res) == 0)
490                         ret = 1;
491                 else
492                         ret = 0;
493         }
494         fclose(fp);
495
496         return ret;
497 }
498
499 char *dereference_tizen_exe_path(const char *path, char *resolved)
500 {
501         char *res = NULL;
502         char tmp_path[PATH_MAX];
503
504         resolved[0] = 0;
505         //try resolve <path>.exe
506         sprintf(tmp_path, "%s.exe", path);
507         if ((res = realpath(tmp_path, resolved)) == NULL) {
508                 //try to resolve path <path>
509                 res = realpath(path, resolved);
510         }
511
512         return res;
513 }
514
515 float get_uptime(void)
516 {
517         const char *LINUX_UPTIME_FILE = "/proc/uptime";
518         FILE *fp = fopen(LINUX_UPTIME_FILE, "r");
519         float uptime;
520         if (!fp)
521                 return 0.0;
522
523         if (fscanf(fp, "%f", &uptime) != 1)
524                 uptime = 0.0;
525
526         fclose(fp);
527         return uptime;
528 }