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