cac6db1e3c0a01d2767f6a8c75b24ef646760080
[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                                                 return -1;
162                                 }
163                         } else {
164                                 ret = remove(abs_filename);
165                                 if (ret <0)
166                                         return -1;
167                         }
168                 }
169                 (void)closedir(dp);
170                 ret = remove(dirname);
171                 if (ret <0)
172                         return -1;
173         } else {
174                 app2ext_print("Couldn't open the directory[%s]\n", dirname);
175         }
176         return 0;
177 }
178
179 int _app2sd_copy_dir(const char *src, const char *dest)
180 {
181         int ret = APP2EXT_SUCCESS;
182         const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
183         ret = _xsystem(argv_bin);
184         if (ret) {
185                 app2ext_print("copy fail\n");
186                 return APP2EXT_ERROR_MOVE;
187         }
188         return ret;
189 }
190
191 int _app2sd_rename_dir(const char *old_name, const char *new_name)
192 {
193         int ret = APP2EXT_SUCCESS;
194         const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
195         ret = _xsystem(argv_bin);
196         if (ret) {
197                 app2ext_print("mv/rename fail\n");
198                 return APP2EXT_ERROR_MOVE;
199         }
200         return ret;
201 }
202
203 unsigned long long _app2sd_calculate_dir_size(char *dirname)
204 {
205         static unsigned long long total = 0;
206         DIR *dp = NULL;
207         struct dirent *ep = NULL;
208         char abs_filename[FILENAME_MAX] = { 0, };;
209         dp = opendir(dirname);
210         if (dp != NULL) {
211                 while ((ep = readdir(dp)) != NULL) {
212                         struct stat stFileInfo;
213
214                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
215                                  ep->d_name);
216
217                         if (stat(abs_filename, &stFileInfo) < 0)
218                                 perror(abs_filename);
219                         else {
220                                 total += stFileInfo.st_size;
221
222                                 if (S_ISDIR(stFileInfo.st_mode)) {
223                                         if (strcmp(ep->d_name, ".")
224                                             && strcmp(ep->d_name, "..")) {
225                                                 _app2sd_calculate_dir_size
226                                                     (abs_filename);
227                                         }
228                                 } else {
229                                         /*Do Nothing */
230                                 }
231                         }
232                 }
233                 (void)closedir(dp);
234         } else {
235                 app2ext_print("\n error in opening directory ");
236         }
237         return total;
238 }
239
240 unsigned long long _app2sd_calculate_file_size(const char *filename)
241 {
242         struct stat stFileInfo;
243         app2ext_print("\n Calculating file size for %s\n", filename);
244
245         if (stat(filename, &stFileInfo) < 0) {
246                 perror(filename);
247                 return 0;
248         } else
249                 return stFileInfo.st_size;
250 }
251
252 /*Note: Don't use any printf statement inside this function*/
253 char *_app2sd_encrypt_device(const char *device, const char *pkgid,
254                               char *passwd)
255 {
256         const char *argv[] =
257             { "/sbin/losetup", "-e", "aes", device, pkgid, "-k", passwd, NULL };
258         pid_t pid = 0;
259         int my_pipe[2] = { 0, };
260         char buf[FILENAME_MAX] = { 0, };
261         char *ret_result = NULL;
262         int result = 0;
263         if (pipe(my_pipe) < 0) {
264                 fprintf(stderr, "Unable to create pipe\n");
265                 return NULL;
266         }
267         pid = fork();
268         switch (pid) {
269         case -1:
270                 perror("fork failed");
271                 return NULL;
272         case 0:
273                 /* child */
274                 close(1);
275                 close(2);
276                 result = dup(my_pipe[1]);
277                 if (result < 0) {
278                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
279                         _exit(-1);
280                 }
281                 result = dup(my_pipe[1]);
282                 if (result < 0) {
283                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
284                         _exit(-1);
285                 }
286                 if (execvp(argv[0], (char *const *)argv) < 0) {
287                         fprintf(stderr, "execvp failed %d....%s\n", errno, strerror(errno));    /*Don't use d_msg_app2sd */
288                 }
289                 _exit(-1);
290         default:
291                 /* parent */
292                 close(my_pipe[1]);
293                 result = read(my_pipe[0], buf, FILENAME_MAX);
294                 if (result < 0)
295                         fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
296                 break;
297         }
298
299         ret_result = (char *)malloc(strlen(buf) + 1);
300         if (ret_result == NULL) {
301                 app2ext_print("Malloc failed!\n");
302                 return NULL;
303         }
304         memset(ret_result, '\0', strlen(buf) + 1);
305         memcpy(ret_result, buf, strlen(buf));
306         return ret_result;
307 }
308
309 /*Note: Don't use any printf statement inside this function*/
310 char *_app2sd_detach_loop_device(const char *device)
311 {
312         const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
313         pid_t pid;
314         int my_pipe[2] = { 0, };
315         char buf[FILENAME_MAX] = { 0, };
316         char *ret_result = NULL;
317         int result = 0;
318         if (pipe(my_pipe) < 0) {
319                 fprintf(stderr, "Unable to create pipe\n");
320                 return NULL;
321         }
322         pid = fork();
323         switch (pid) {
324         case -1:
325                 perror("fork failed");
326                 return NULL;
327         case 0:
328                 /* child */
329                 close(1);
330                 close(2);
331                 result = dup(my_pipe[1]);
332                 if (result < 0) {
333                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
334                         _exit(-1);
335                 }
336                 result = dup(my_pipe[1]);
337                 if (result < 0) {
338                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
339                         _exit(-1);
340                 }
341                 if (execvp(argv[0], (char *const *)argv) < 0) {
342                         fprintf(stderr, "execvp failed\n");     /*Don't use d_msg_app2sd */
343                 }
344                 _exit(-1);
345         default:
346                 /* parent */
347                 close(my_pipe[1]);
348                 result = read(my_pipe[0], buf, FILENAME_MAX);
349                 if (result < 0)
350                         fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
351                 break;
352         }
353
354         ret_result = (char *)malloc(strlen(buf) + 1);
355         if (ret_result == NULL) {
356                 app2ext_print("Malloc failed!\n");
357                 return NULL;
358         }
359         memset(ret_result, '\0', strlen(buf) + 1);
360         memcpy(ret_result, buf, strlen(buf));
361
362         return ret_result;
363 }
364
365 /*Note: Don't use any printf statement inside this function*/
366 char *_app2sd_find_associated_device(const char *mmc_app_path)
367 {
368         const char *argv[] = { "/sbin/losetup", "-j", mmc_app_path, NULL };
369         pid_t pid;
370         int my_pipe[2] = { 0, };
371         char buf[FILENAME_MAX] = { 0, };
372         char *ret_result = NULL;
373         int result = 0;
374         if (pipe(my_pipe) < 0) {
375                 fprintf(stderr, "Unable to create pipe\n");
376                 return NULL;
377         }
378         pid = fork();
379         switch (pid) {
380         case -1:
381                 perror("fork failed");
382                 return NULL;
383         case 0:
384                 /* child */
385                 close(1);
386                 close(2);
387                 result = dup(my_pipe[1]);
388                 if (result < 0) {
389                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
390                         _exit(-1);
391                 }
392                 result = dup(my_pipe[1]);
393                 if (result < 0) {
394                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
395                         _exit(-1);
396                 }
397                 if (execvp(argv[0], (char *const *)argv) < 0) {
398                         fprintf(stderr, "execvp failed\n");     /*Don't use d_msg_app2sd */
399                 }
400                 _exit(-1);
401         default:
402                 /* parent */
403                 close(my_pipe[1]);
404                 result = read(my_pipe[0], buf, FILENAME_MAX);
405                 if (result < 0)
406                         fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
407                 break;
408         }
409
410         ret_result = (char *)malloc(strlen(buf) + 1);
411         if (ret_result == NULL) {
412                 app2ext_print("Malloc failed!\n");
413                 return NULL;
414         }
415         memset(ret_result, '\0', strlen(buf) + 1);
416         memcpy(ret_result, buf, strlen(buf));
417
418         return ret_result;
419 }
420
421 /*Note: Don't use any printf statement inside this function*/
422 char *_app2sd_find_free_device(void)
423 {
424         const char *argv[] = { "/sbin/losetup", "-f", NULL };
425         pid_t pid;
426         int my_pipe[2] = { 0, };
427         char buf[FILENAME_MAX+1] = { 0, };
428         char *ret_result = NULL;
429         int result = 0;
430         if (pipe(my_pipe) < 0) {
431                 fprintf(stderr, "Unable to create pipe\n");
432                 return NULL;
433         }
434         pid = fork();
435         switch (pid) {
436         case -1:
437                 perror("fork failed");
438                 return NULL;
439         case 0:
440                 /* child */
441                 close(1);
442                 close(2);
443                 result = dup(my_pipe[1]);
444                 if (result < 0) {
445                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
446                         _exit(-1);
447                 }
448                 result = dup(my_pipe[1]);
449                 if (result < 0) {
450                         fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
451                         _exit(-1);
452                 }
453                 if (execvp(argv[0], (char *const *)argv) < 0) {
454                         fprintf(stderr, "execvp failed\n");     /*Don't use d_msg_app2sd */
455                 }
456                 _exit(-1);
457         default:
458                 /* parent */
459                 close(my_pipe[1]);
460                 result = read(my_pipe[0], buf, FILENAME_MAX);
461                 if (result < 0)
462                         fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
463                 break;
464         }
465
466         ret_result = (char *)malloc(strlen(buf) + 1);
467         if (ret_result == NULL) {
468                 app2ext_print("Malloc failed!\n");
469                 return NULL;
470         }
471         memset(ret_result, '\0', strlen(buf) + 1);
472         memcpy(ret_result, buf, strlen(buf));
473
474         return ret_result;
475 }
476
477 /*@_app2sd_generate_password
478 * This is a simple password generator
479 * return: On success, it will return the password, else NULL.
480 */
481 char *_app2sd_generate_password(const char *pkgid)
482 {
483         char passwd[PASSWD_LEN+1] = { 0, };
484         char *ret_result = NULL;
485         char set[ASCII_PASSWD_CHAR+1] = "!\"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
486         unsigned char char_1;
487         unsigned char char_2;
488         int i = 0;
489         int appname_len = strlen(pkgid);
490         int j = appname_len;
491
492         /* Length of the password */
493         ret_result = (char*)malloc(PASSWD_LEN+1);
494         if (NULL == ret_result) {
495                 app2ext_print("Unable to Allocate memory\n");
496                 return NULL;
497         }
498         memset((void *)ret_result, '\0', PASSWD_LEN+1);
499
500         while(i < PASSWD_LEN) {
501                 char_1 = (rand()+pkgid[j--])%ASCII_PASSWD_CHAR;
502                 char_2 = rand()%ASCII_PASSWD_CHAR;
503                 passwd[i] = set[char_1];
504                 passwd[i+1] = set[(pkgid[j--])*2];
505                 if (i<PASSWD_LEN-3)
506                         passwd[i+2] = set[char_2];
507                 i++;
508         }
509
510         app2ext_print("Password is %s\n", passwd);
511         memcpy(ret_result, passwd, PASSWD_LEN+1);
512         return ret_result;
513 }
514
515 /*@_app2sd_setup_path
516 * change smack label given groupid
517 * return: On success, it will return the password, else NULL.
518 */
519 int _app2sd_setup_path(const char *pkgid, const char *dirpath,
520                                                 int apppathtype, const char *groupid)
521 {
522         int ret = 0;
523         void *handle = NULL;
524         char *errmsg = NULL;
525         int (*perm_app_setup_path)(const char*, const char*, int, ...) = NULL;
526
527         if (pkgid == NULL || dirpath == NULL)
528                 return -1;
529
530         handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
531         if (!handle) {
532                 app2ext_print( "setup path: dlopen() failed. [%s]", dlerror());
533                 return -1;
534         }
535
536         perm_app_setup_path = dlsym(handle, "perm_app_setup_path");
537         errmsg = dlerror();
538         if ((errmsg != NULL) || (perm_app_setup_path == NULL)) {
539                 app2ext_print( "setup path: dlsym() failed. [%s]", errmsg);
540                 dlclose(handle);
541                 return -1;
542         }
543
544         if (groupid == NULL) {
545                 app2ext_print( "[smack] perm_app_setup_path(%s, %s, %d)", pkgid, dirpath, apppathtype);
546                 ret = perm_app_setup_path(pkgid, dirpath, apppathtype);
547                 app2ext_print( "[smack] perm_app_setup_path(), result = [%d]", ret);
548         } else {
549                 app2ext_print( "[smack] perm_app_setup_path(%s, %s, %d, %s)", pkgid, dirpath, apppathtype, groupid);
550                 ret = perm_app_setup_path(pkgid, dirpath, apppathtype, groupid);
551                 app2ext_print( "[smack] perm_app_setup_path(), result = [%d]", ret);
552         }
553
554         dlclose(handle);
555         return ret;
556 }
557