4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Garima Shrivastava<garima.s@samsung.com>
7 * Jyotsna Dhumale <jyotsna.a@samsung.com>
8 * Venkatesha Sarpangala <sarpangala.v@samsung.com>
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
14 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <app2sd_internals.h>
25 #include <app2sd_interface.h>
27 #include <sys/types.h>
31 #include <sys/types.h>
36 #include <sys/statvfs.h>
41 #define ASCII_PASSWD_CHAR 93
42 #define LIB_PRIVILEGE_CONTROL "libprivilege-control.so.0"
45 ########### Internal APIs ##################
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[])
57 perror("fork failed");
61 execvp(argv[0], (char *const *)argv);
67 if (waitpid(pid, &status, 0) == -1) {
68 perror("waitpid failed");
71 if (WIFSIGNALED(status)) {
75 if (!WIFEXITED(status)) {
76 /* shouldn't happen */
77 perror("should not happen");
80 return WEXITSTATUS(status);
85 * @_app2sd_check_mmc_status
86 * This function checks and returns MMC status
88 int _app2sd_check_mmc_status(void)
92 fp1 = fopen("/etc/mtab", "r");
94 fprintf(stderr, "failed to open file\n");
95 app2ext_print("failed to open file /etc/mtab\n");
96 return APP2EXT_ERROR_MMC_STATUS;
98 while (fgets(line, 512, fp1) != NULL) {
99 if (strstr(line, MMC_PATH) != NULL) {
101 return APP2EXT_SUCCESS;
105 return APP2EXT_ERROR_MMC_STATUS;
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.
117 int _app2sd_get_available_free_memory(const char *sd_path, int *free_mem)
121 if (sd_path == NULL || free_mem == NULL) {
122 app2ext_print("App2Sd Error : Invalid input parameter\n");
125 memset((void *)&buf, '\0', sizeof(struct statvfs));
126 ret = statvfs(sd_path, &buf);
129 ("App2SD Error: Unable to get SD Card memory information\n");
130 return APP2EXT_ERROR_MMC_INFORMATION;
132 *free_mem = ((buf.f_bfree * buf.f_bsize) / 1024) / 1024;
136 int _app2sd_delete_directory(char *dirname)
139 struct dirent *ep = NULL;
140 char abs_filename[FILENAME_MAX] = { 0, };
142 dp = opendir(dirname);
144 while ((ep = readdir(dp)) != NULL) {
145 struct stat stFileInfo;
147 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
150 if (lstat(abs_filename, &stFileInfo) < 0) {
151 perror(abs_filename);
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);
166 ret = remove(abs_filename);
174 ret = remove(dirname);
178 app2ext_print("Couldn't open the directory[%s]\n", dirname);
183 int _app2sd_copy_dir(const char *src, const char *dest)
185 int ret = APP2EXT_SUCCESS;
186 const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
187 ret = _xsystem(argv_bin);
189 app2ext_print("copy fail\n");
190 return APP2EXT_ERROR_MOVE;
195 int _app2sd_rename_dir(const char *old_name, const char *new_name)
197 int ret = APP2EXT_SUCCESS;
198 const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
199 ret = _xsystem(argv_bin);
201 app2ext_print("mv/rename fail\n");
202 return APP2EXT_ERROR_MOVE;
207 unsigned long long _app2sd_calculate_dir_size(char *dirname)
209 static unsigned long long total = 0;
211 struct dirent *ep = NULL;
212 char abs_filename[FILENAME_MAX] = { 0, };;
213 dp = opendir(dirname);
215 while ((ep = readdir(dp)) != NULL) {
216 struct stat stFileInfo;
218 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
221 if (stat(abs_filename, &stFileInfo) < 0)
222 perror(abs_filename);
224 total += stFileInfo.st_size;
226 if (S_ISDIR(stFileInfo.st_mode)) {
227 if (strcmp(ep->d_name, ".")
228 && strcmp(ep->d_name, "..")) {
229 _app2sd_calculate_dir_size
239 app2ext_print("\n error in opening directory ");
244 unsigned long long _app2sd_calculate_file_size(const char *filename)
246 struct stat stFileInfo;
247 app2ext_print("\n Calculating file size for %s\n", filename);
249 if (stat(filename, &stFileInfo) < 0) {
253 return stFileInfo.st_size;
256 /*Note: Don't use any printf statement inside this function*/
257 char *_app2sd_encrypt_device(const char *device, const char *pkgid,
261 { "/sbin/losetup", "-e", "aes", device, pkgid, "-k", passwd, NULL };
263 int my_pipe[2] = { 0, };
264 char buf[FILENAME_MAX] = { 0, };
265 char *ret_result = NULL;
267 if (pipe(my_pipe) < 0) {
268 fprintf(stderr, "Unable to create pipe\n");
274 perror("fork failed");
280 result = dup(my_pipe[1]);
282 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
285 result = dup(my_pipe[1]);
287 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
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 */
297 result = read(my_pipe[0], buf, FILENAME_MAX);
299 fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
303 ret_result = (char *)malloc(strlen(buf) + 1);
304 if (ret_result == NULL) {
305 app2ext_print("Malloc failed!\n");
308 memset(ret_result, '\0', strlen(buf) + 1);
309 memcpy(ret_result, buf, strlen(buf));
313 /*Note: Don't use any printf statement inside this function*/
314 char *_app2sd_detach_loop_device(const char *device)
316 const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
318 int my_pipe[2] = { 0, };
319 char buf[FILENAME_MAX] = { 0, };
320 char *ret_result = NULL;
322 if (pipe(my_pipe) < 0) {
323 fprintf(stderr, "Unable to create pipe\n");
329 perror("fork failed");
335 result = dup(my_pipe[1]);
337 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
340 result = dup(my_pipe[1]);
342 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
345 if (execvp(argv[0], (char *const *)argv) < 0) {
346 fprintf(stderr, "execvp failed\n"); /*Don't use d_msg_app2sd */
352 result = read(my_pipe[0], buf, FILENAME_MAX);
354 fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
358 ret_result = (char *)malloc(strlen(buf) + 1);
359 if (ret_result == NULL) {
360 app2ext_print("Malloc failed!\n");
363 memset(ret_result, '\0', strlen(buf) + 1);
364 memcpy(ret_result, buf, strlen(buf));
369 /*Note: Don't use any printf statement inside this function*/
370 char *_app2sd_find_associated_device(const char *mmc_app_path)
372 const char *argv[] = { "/sbin/losetup", "-j", mmc_app_path, NULL };
374 int my_pipe[2] = { 0, };
375 char buf[FILENAME_MAX] = { 0, };
376 char *ret_result = NULL;
378 if (pipe(my_pipe) < 0) {
379 fprintf(stderr, "Unable to create pipe\n");
385 perror("fork failed");
391 result = dup(my_pipe[1]);
393 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
396 result = dup(my_pipe[1]);
398 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
401 if (execvp(argv[0], (char *const *)argv) < 0) {
402 fprintf(stderr, "execvp failed\n"); /*Don't use d_msg_app2sd */
408 result = read(my_pipe[0], buf, FILENAME_MAX);
410 fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
414 ret_result = (char *)malloc(strlen(buf) + 1);
415 if (ret_result == NULL) {
416 app2ext_print("Malloc failed!\n");
419 memset(ret_result, '\0', strlen(buf) + 1);
420 memcpy(ret_result, buf, strlen(buf));
425 /*Note: Don't use any printf statement inside this function*/
426 char *_app2sd_find_free_device(void)
428 const char *argv[] = { "/sbin/losetup", "-f", NULL };
430 int my_pipe[2] = { 0, };
431 char buf[FILENAME_MAX+1] = { 0, };
432 char *ret_result = NULL;
434 if (pipe(my_pipe) < 0) {
435 fprintf(stderr, "Unable to create pipe\n");
441 perror("fork failed");
447 result = dup(my_pipe[1]);
449 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
452 result = dup(my_pipe[1]);
454 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
457 if (execvp(argv[0], (char *const *)argv) < 0) {
458 fprintf(stderr, "execvp failed\n"); /*Don't use d_msg_app2sd */
464 result = read(my_pipe[0], buf, FILENAME_MAX);
466 fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
470 ret_result = (char *)malloc(strlen(buf) + 1);
471 if (ret_result == NULL) {
472 app2ext_print("Malloc failed!\n");
475 memset(ret_result, '\0', strlen(buf) + 1);
476 memcpy(ret_result, buf, strlen(buf));
481 /*@_app2sd_generate_password
482 * This is a simple password generator
483 * return: On success, it will return the password, else NULL.
485 char *_app2sd_generate_password(const char *pkgid)
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;
493 int appname_len = strlen(pkgid);
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");
502 memset((void *)ret_result, '\0', PASSWD_LEN+1);
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];
510 passwd[i+2] = set[char_2];
514 app2ext_print("Password is %s\n", passwd);
515 memcpy(ret_result, passwd, PASSWD_LEN+1);
519 /*@_app2sd_setup_path
520 * change smack label given groupid
521 * return: On success, it will return the password, else NULL.
523 int _app2sd_setup_path(const char *pkgid, const char *dirpath,
524 int apppathtype, const char *groupid)
529 int (*perm_app_setup_path)(const char*, const char*, int, ...) = NULL;
531 if (pkgid == NULL || dirpath == NULL)
534 handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
536 app2ext_print( "setup path: dlopen() failed. [%s]", dlerror());
540 perm_app_setup_path = dlsym(handle, "perm_app_setup_path");
542 if ((errmsg != NULL) || (perm_app_setup_path == NULL)) {
543 app2ext_print( "setup path: dlsym() failed. [%s]", errmsg);
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);
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);