Fix HANDLE_LEAK
[platform/core/appfw/app2sd.git] / plugin / app2sd / src / app2sd_internals_utils.c
1 /*
2  * app2ext
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Garima Shrivastava<garima.s@samsung.com>
7  *      Jyotsna Dhumale <jyotsna.a@samsung.com>
8  *      Venkatesha Sarpangala <sarpangala.v@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <app2sd_internals.h>
25 #include <app2sd_interface.h>
26
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <sys/types.h>
32 #include <dirent.h>
33 #include <sys/stat.h>
34 #include <time.h>
35 #include <dlog.h>
36 #include <sys/statvfs.h>
37 #include <errno.h>
38 #include <dlfcn.h>
39
40 #define PASSWD_LEN              8
41 #define ASCII_PASSWD_CHAR       93
42 #define LIB_PRIVILEGE_CONTROL           "libprivilege-control.so.0"
43
44 /*
45 ########### Internal APIs ##################
46  */
47
48 /*Note: Don't use any printf statement inside this function*/
49 /*This function is similar to Linux's "system()"  for executing a process.*/
50 int _xsystem(const char *argv[])
51 {
52         int status = 0;
53         pid_t pid;
54         pid = fork();
55         switch (pid) {
56         case -1:
57                 perror("fork failed");
58                 return -1;
59         case 0:
60                 /* child */
61                 execvp(argv[0], (char *const *)argv);
62                 _exit(-1);
63         default:
64                 /* parent */
65                 break;
66         }
67         if (waitpid(pid, &status, 0) == -1) {
68                 perror("waitpid failed");
69                 return -1;
70         }
71         if (WIFSIGNALED(status)) {
72                 perror("signal");
73                 return -1;
74         }
75         if (!WIFEXITED(status)) {
76                 /* shouldn't happen */
77                 perror("should not happen");
78                 return -1;
79         }
80         return WEXITSTATUS(status);
81 }
82
83
84 /*
85 * @_app2sd_check_mmc_status
86 * This function checks and returns MMC status
87 */
88 int _app2sd_check_mmc_status(void)
89 {
90         FILE *fp1 = NULL;
91         char line[512];
92         fp1 = fopen("/etc/mtab", "r");
93         if (fp1 == NULL) {
94                 fprintf(stderr, "failed to open file\n");
95                 app2ext_print("failed to open file /etc/mtab\n");
96                 return APP2EXT_ERROR_MMC_STATUS;
97         }
98         while (fgets(line, 512, fp1) != NULL) {
99                 if (strstr(line, MMC_PATH) != NULL) {
100                         fclose(fp1);
101                         return APP2EXT_SUCCESS;
102                 }
103         }
104         fclose(fp1);
105         return APP2EXT_ERROR_MMC_STATUS;
106 }
107
108 /*
109  * @_app2sd_get_available_free_memory
110  * This function returns the available free memory in the SD Card.
111  * param [in]: sd_path: This is sd card access path.
112  * param [out]: free_mem: Result will be available in this.
113  * User has to pass valid memory address.
114  * return: On success, it will return 0.
115  * Else, appropriate error no will be returned.
116  */
117 int _app2sd_get_available_free_memory(const char *sd_path, int *free_mem)
118 {
119         struct statvfs buf;
120         int ret = 0;
121         if (sd_path == NULL || free_mem == NULL) {
122                 app2ext_print("App2Sd Error : Invalid input parameter\n");
123                 return -1;
124         }
125         memset((void *)&buf, '\0', sizeof(struct statvfs));
126         ret = statvfs(sd_path, &buf);
127         if (ret) {
128                 app2ext_print
129                     ("App2SD Error: Unable to get SD Card memory information\n");
130                 return APP2EXT_ERROR_MMC_INFORMATION;
131         }
132         *free_mem = ((buf.f_bfree * buf.f_bsize) / 1024) / 1024;
133         return 0;
134 }
135
136 int _app2sd_delete_directory(char *dirname)
137 {
138         DIR *dp = NULL;
139         struct dirent *ep = NULL;
140         char abs_filename[FILENAME_MAX] = { 0, };
141         int ret = 0;
142         dp = opendir(dirname);
143         if (dp != NULL) {
144                 while ((ep = readdir(dp)) != NULL) {
145                         struct stat stFileInfo;
146
147                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
148                                 ep->d_name);
149
150                         if (lstat(abs_filename, &stFileInfo) < 0) {
151                                 perror(abs_filename);
152                                 closedir(dp);
153                                 return -1;
154                         }
155
156                         if (S_ISDIR(stFileInfo.st_mode)) {
157                                 if (strcmp(ep->d_name, ".")
158                                     && strcmp(ep->d_name, "..")) {
159                                         ret = _app2sd_delete_directory(abs_filename);
160                                         if (ret < 0) {
161                                                 closedir(dp);
162                                                 return -1;
163                                         }
164                                 }
165                         } else {
166                                 ret = remove(abs_filename);
167                                 if (ret < 0) {
168                                         closedir(dp);
169                                         return -1;
170                                 }
171                         }
172                 }
173                 (void)closedir(dp);
174                 ret = remove(dirname);
175                 if (ret < 0)
176                         return -1;
177         } else {
178                 app2ext_print("Couldn't open the directory[%s]\n", dirname);
179         }
180         return 0;
181 }
182
183 int _app2sd_copy_dir(const char *src, const char *dest)
184 {
185         int ret = APP2EXT_SUCCESS;
186         const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
187         ret = _xsystem(argv_bin);
188         if (ret) {
189                 app2ext_print("copy fail\n");
190                 return APP2EXT_ERROR_MOVE;
191         }
192         return ret;
193 }
194
195 int _app2sd_rename_dir(const char *old_name, const char *new_name)
196 {
197         int ret = APP2EXT_SUCCESS;
198         const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
199         ret = _xsystem(argv_bin);
200         if (ret) {
201                 app2ext_print("mv/rename fail\n");
202                 return APP2EXT_ERROR_MOVE;
203         }
204         return ret;
205 }
206
207 unsigned long long _app2sd_calculate_dir_size(char *dirname)
208 {
209         static unsigned long long total = 0;
210         DIR *dp = NULL;
211         struct dirent *ep = NULL;
212         char abs_filename[FILENAME_MAX] = { 0, };;
213         dp = opendir(dirname);
214         if (dp != NULL) {
215                 while ((ep = readdir(dp)) != NULL) {
216                         struct stat stFileInfo;
217
218                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
219                                  ep->d_name);
220
221                         if (stat(abs_filename, &stFileInfo) < 0)
222                                 perror(abs_filename);
223                         else {
224                                 total += stFileInfo.st_size;
225
226                                 if (S_ISDIR(stFileInfo.st_mode)) {
227                                         if (strcmp(ep->d_name, ".")
228                                             && strcmp(ep->d_name, "..")) {
229                                                 _app2sd_calculate_dir_size
230                                                     (abs_filename);
231                                         }
232                                 } else {
233                                         /*Do Nothing */
234                                 }
235                         }
236                 }
237                 (void)closedir(dp);
238         } else {
239                 app2ext_print("\n error in opening directory ");
240         }
241         return total;
242 }
243
244 unsigned long long _app2sd_calculate_file_size(const char *filename)
245 {
246         struct stat stFileInfo;
247         app2ext_print("\n Calculating file size for %s\n", filename);
248
249         if (stat(filename, &stFileInfo) < 0) {
250                 perror(filename);
251                 return 0;
252         } else
253                 return stFileInfo.st_size;
254 }
255
256 /*Note: Don't use any printf statement inside this function*/
257 char *_app2sd_encrypt_device(const char *device, const char *pkgid,
258                               char *passwd)
259 {
260         const char *argv[] =
261             { "/sbin/losetup", "-e", "aes", device, pkgid, "-k", passwd, NULL };
262         pid_t pid = 0;
263         int my_pipe[2] = { 0, };
264         char buf[FILENAME_MAX] = { 0, };
265         char *ret_result = NULL;
266         int result = 0;
267         if (pipe(my_pipe) < 0) {
268                 fprintf(stderr, "Unable to create pipe\n");
269                 return NULL;
270         }
271         pid = fork();
272         switch (pid) {
273         case -1:
274                 perror("fork failed");
275                 return NULL;
276         case 0:
277                 /* child */
278                 close(1);
279                 close(2);
280                 result = dup(my_pipe[1]);
281                 if (result < 0) {
282                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
283                         _exit(-1);
284                 }
285                 result = dup(my_pipe[1]);
286                 if (result < 0) {
287                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
288                         _exit(-1);
289                 }
290                 if (execvp(argv[0], (char *const *)argv) < 0) {
291                         fprintf(stderr, "execvp failed %d....%s\n", errno, strerror(errno));    /*Don't use d_msg_app2sd */
292                 }
293                 _exit(-1);
294         default:
295                 /* parent */
296                 close(my_pipe[1]);
297                 result = read(my_pipe[0], buf, FILENAME_MAX);
298                 if (result < 0)
299                         fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
300                 break;
301         }
302
303         ret_result = (char *)malloc(strlen(buf) + 1);
304         if (ret_result == NULL) {
305                 app2ext_print("Malloc failed!\n");
306                 return NULL;
307         }
308         memset(ret_result, '\0', strlen(buf) + 1);
309         memcpy(ret_result, buf, strlen(buf));
310         return ret_result;
311 }
312
313 /*Note: Don't use any printf statement inside this function*/
314 char *_app2sd_detach_loop_device(const char *device)
315 {
316         const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
317         pid_t pid;
318         int my_pipe[2] = { 0, };
319         char buf[FILENAME_MAX] = { 0, };
320         char *ret_result = NULL;
321         int result = 0;
322         if (pipe(my_pipe) < 0) {
323                 fprintf(stderr, "Unable to create pipe\n");
324                 return NULL;
325         }
326         pid = fork();
327         switch (pid) {
328         case -1:
329                 perror("fork failed");
330                 return NULL;
331         case 0:
332                 /* child */
333                 close(1);
334                 close(2);
335                 result = dup(my_pipe[1]);
336                 if (result < 0) {
337                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
338                         _exit(-1);
339                 }
340                 result = dup(my_pipe[1]);
341                 if (result < 0) {
342                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
343                         _exit(-1);
344                 }
345                 if (execvp(argv[0], (char *const *)argv) < 0) {
346                         fprintf(stderr, "execvp failed\n");     /*Don't use d_msg_app2sd */
347                 }
348                 _exit(-1);
349         default:
350                 /* parent */
351                 close(my_pipe[1]);
352                 result = read(my_pipe[0], buf, FILENAME_MAX);
353                 if (result < 0)
354                         fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
355                 break;
356         }
357
358         ret_result = (char *)malloc(strlen(buf) + 1);
359         if (ret_result == NULL) {
360                 app2ext_print("Malloc failed!\n");
361                 return NULL;
362         }
363         memset(ret_result, '\0', strlen(buf) + 1);
364         memcpy(ret_result, buf, strlen(buf));
365
366         return ret_result;
367 }
368
369 /*Note: Don't use any printf statement inside this function*/
370 char *_app2sd_find_associated_device(const char *mmc_app_path)
371 {
372         const char *argv[] = { "/sbin/losetup", "-j", mmc_app_path, NULL };
373         pid_t pid;
374         int my_pipe[2] = { 0, };
375         char buf[FILENAME_MAX] = { 0, };
376         char *ret_result = NULL;
377         int result = 0;
378         if (pipe(my_pipe) < 0) {
379                 fprintf(stderr, "Unable to create pipe\n");
380                 return NULL;
381         }
382         pid = fork();
383         switch (pid) {
384         case -1:
385                 perror("fork failed");
386                 return NULL;
387         case 0:
388                 /* child */
389                 close(1);
390                 close(2);
391                 result = dup(my_pipe[1]);
392                 if (result < 0) {
393                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
394                         _exit(-1);
395                 }
396                 result = dup(my_pipe[1]);
397                 if (result < 0) {
398                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
399                         _exit(-1);
400                 }
401                 if (execvp(argv[0], (char *const *)argv) < 0) {
402                         fprintf(stderr, "execvp failed\n");     /*Don't use d_msg_app2sd */
403                 }
404                 _exit(-1);
405         default:
406                 /* parent */
407                 close(my_pipe[1]);
408                 result = read(my_pipe[0], buf, FILENAME_MAX);
409                 if (result < 0)
410                         fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
411                 break;
412         }
413
414         ret_result = (char *)malloc(strlen(buf) + 1);
415         if (ret_result == NULL) {
416                 app2ext_print("Malloc failed!\n");
417                 return NULL;
418         }
419         memset(ret_result, '\0', strlen(buf) + 1);
420         memcpy(ret_result, buf, strlen(buf));
421
422         return ret_result;
423 }
424
425 /*Note: Don't use any printf statement inside this function*/
426 char *_app2sd_find_free_device(void)
427 {
428         const char *argv[] = { "/sbin/losetup", "-f", NULL };
429         pid_t pid;
430         int my_pipe[2] = { 0, };
431         char buf[FILENAME_MAX+1] = { 0, };
432         char *ret_result = NULL;
433         int result = 0;
434         if (pipe(my_pipe) < 0) {
435                 fprintf(stderr, "Unable to create pipe\n");
436                 return NULL;
437         }
438         pid = fork();
439         switch (pid) {
440         case -1:
441                 perror("fork failed");
442                 return NULL;
443         case 0:
444                 /* child */
445                 close(1);
446                 close(2);
447                 result = dup(my_pipe[1]);
448                 if (result < 0) {
449                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
450                         _exit(-1);
451                 }
452                 result = dup(my_pipe[1]);
453                 if (result < 0) {
454                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
455                         _exit(-1);
456                 }
457                 if (execvp(argv[0], (char *const *)argv) < 0) {
458                         fprintf(stderr, "execvp failed\n");     /*Don't use d_msg_app2sd */
459                 }
460                 _exit(-1);
461         default:
462                 /* parent */
463                 close(my_pipe[1]);
464                 result = read(my_pipe[0], buf, FILENAME_MAX);
465                 if (result < 0)
466                         fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
467                 break;
468         }
469
470         ret_result = (char *)malloc(strlen(buf) + 1);
471         if (ret_result == NULL) {
472                 app2ext_print("Malloc failed!\n");
473                 return NULL;
474         }
475         memset(ret_result, '\0', strlen(buf) + 1);
476         memcpy(ret_result, buf, strlen(buf));
477
478         return ret_result;
479 }
480
481 /*@_app2sd_generate_password
482 * This is a simple password generator
483 * return: On success, it will return the password, else NULL.
484 */
485 char *_app2sd_generate_password(const char *pkgid)
486 {
487         char passwd[PASSWD_LEN+1] = { 0, };
488         char *ret_result = NULL;
489         char set[ASCII_PASSWD_CHAR+1] = "!\"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
490         unsigned char char_1;
491         unsigned char char_2;
492         int i = 0;
493         int appname_len = strlen(pkgid);
494         int j = appname_len;
495
496         /* Length of the password */
497         ret_result = (char*)malloc(PASSWD_LEN+1);
498         if (NULL == ret_result) {
499                 app2ext_print("Unable to Allocate memory\n");
500                 return NULL;
501         }
502         memset((void *)ret_result, '\0', PASSWD_LEN+1);
503
504         while(i < PASSWD_LEN) {
505                 char_1 = (rand()+pkgid[j--])%ASCII_PASSWD_CHAR;
506                 char_2 = rand()%ASCII_PASSWD_CHAR;
507                 passwd[i] = set[char_1];
508                 passwd[i+1] = set[(pkgid[j--])*2];
509                 if (i<PASSWD_LEN-3)
510                         passwd[i+2] = set[char_2];
511                 i++;
512         }
513
514         app2ext_print("Password is %s\n", passwd);
515         memcpy(ret_result, passwd, PASSWD_LEN+1);
516         return ret_result;
517 }
518
519 /*@_app2sd_setup_path
520 * change smack label given groupid
521 * return: On success, it will return the password, else NULL.
522 */
523 int _app2sd_setup_path(const char *pkgid, const char *dirpath,
524                                                 int apppathtype, const char *groupid)
525 {
526         int ret = 0;
527         void *handle = NULL;
528         char *errmsg = NULL;
529         int (*perm_app_setup_path)(const char*, const char*, int, ...) = NULL;
530
531         if (pkgid == NULL || dirpath == NULL)
532                 return -1;
533
534         handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
535         if (!handle) {
536                 app2ext_print( "setup path: dlopen() failed. [%s]", dlerror());
537                 return -1;
538         }
539
540         perm_app_setup_path = dlsym(handle, "perm_app_setup_path");
541         errmsg = dlerror();
542         if ((errmsg != NULL) || (perm_app_setup_path == NULL)) {
543                 app2ext_print( "setup path: dlsym() failed. [%s]", errmsg);
544                 dlclose(handle);
545                 return -1;
546         }
547
548         if (groupid == NULL) {
549                 app2ext_print( "[smack] perm_app_setup_path(%s, %s, %d)", pkgid, dirpath, apppathtype);
550                 ret = perm_app_setup_path(pkgid, dirpath, apppathtype);
551                 app2ext_print( "[smack] perm_app_setup_path(), result = [%d]", ret);
552         } else {
553                 app2ext_print( "[smack] perm_app_setup_path(%s, %s, %d, %s)", pkgid, dirpath, apppathtype, groupid);
554                 ret = perm_app_setup_path(pkgid, dirpath, apppathtype, groupid);
555                 app2ext_print( "[smack] perm_app_setup_path(), result = [%d]", ret);
556         }
557
558         dlclose(handle);
559         return ret;
560 }
561