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);
164 ret = remove(abs_filename);
170 ret = remove(dirname);
174 app2ext_print("Couldn't open the directory[%s]\n", dirname);
179 int _app2sd_copy_dir(const char *src, const char *dest)
181 int ret = APP2EXT_SUCCESS;
182 const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
183 ret = _xsystem(argv_bin);
185 app2ext_print("copy fail\n");
186 return APP2EXT_ERROR_MOVE;
191 int _app2sd_rename_dir(const char *old_name, const char *new_name)
193 int ret = APP2EXT_SUCCESS;
194 const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
195 ret = _xsystem(argv_bin);
197 app2ext_print("mv/rename fail\n");
198 return APP2EXT_ERROR_MOVE;
203 unsigned long long _app2sd_calculate_dir_size(char *dirname)
205 static unsigned long long total = 0;
207 struct dirent *ep = NULL;
208 char abs_filename[FILENAME_MAX] = { 0, };;
209 dp = opendir(dirname);
211 while ((ep = readdir(dp)) != NULL) {
212 struct stat stFileInfo;
214 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
217 if (stat(abs_filename, &stFileInfo) < 0)
218 perror(abs_filename);
220 total += stFileInfo.st_size;
222 if (S_ISDIR(stFileInfo.st_mode)) {
223 if (strcmp(ep->d_name, ".")
224 && strcmp(ep->d_name, "..")) {
225 _app2sd_calculate_dir_size
235 app2ext_print("\n error in opening directory ");
240 unsigned long long _app2sd_calculate_file_size(const char *filename)
242 struct stat stFileInfo;
243 app2ext_print("\n Calculating file size for %s\n", filename);
245 if (stat(filename, &stFileInfo) < 0) {
249 return stFileInfo.st_size;
252 /*Note: Don't use any printf statement inside this function*/
253 char *_app2sd_encrypt_device(const char *device, const char *pkgid,
257 { "/sbin/losetup", "-e", "aes", device, pkgid, "-k", passwd, NULL };
259 int my_pipe[2] = { 0, };
260 char buf[FILENAME_MAX] = { 0, };
261 char *ret_result = NULL;
263 if (pipe(my_pipe) < 0) {
264 fprintf(stderr, "Unable to create pipe\n");
270 perror("fork failed");
276 result = dup(my_pipe[1]);
278 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
281 result = dup(my_pipe[1]);
283 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
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 */
293 result = read(my_pipe[0], buf, FILENAME_MAX);
295 fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
299 ret_result = (char *)malloc(strlen(buf) + 1);
300 if (ret_result == NULL) {
301 app2ext_print("Malloc failed!\n");
304 memset(ret_result, '\0', strlen(buf) + 1);
305 memcpy(ret_result, buf, strlen(buf));
309 /*Note: Don't use any printf statement inside this function*/
310 char *_app2sd_detach_loop_device(const char *device)
312 const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
314 int my_pipe[2] = { 0, };
315 char buf[FILENAME_MAX] = { 0, };
316 char *ret_result = NULL;
318 if (pipe(my_pipe) < 0) {
319 fprintf(stderr, "Unable to create pipe\n");
325 perror("fork failed");
331 result = dup(my_pipe[1]);
333 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
336 result = dup(my_pipe[1]);
338 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
341 if (execvp(argv[0], (char *const *)argv) < 0) {
342 fprintf(stderr, "execvp failed\n"); /*Don't use d_msg_app2sd */
348 result = read(my_pipe[0], buf, FILENAME_MAX);
350 fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
354 ret_result = (char *)malloc(strlen(buf) + 1);
355 if (ret_result == NULL) {
356 app2ext_print("Malloc failed!\n");
359 memset(ret_result, '\0', strlen(buf) + 1);
360 memcpy(ret_result, buf, strlen(buf));
365 /*Note: Don't use any printf statement inside this function*/
366 char *_app2sd_find_associated_device(const char *mmc_app_path)
368 const char *argv[] = { "/sbin/losetup", "-j", mmc_app_path, NULL };
370 int my_pipe[2] = { 0, };
371 char buf[FILENAME_MAX] = { 0, };
372 char *ret_result = NULL;
374 if (pipe(my_pipe) < 0) {
375 fprintf(stderr, "Unable to create pipe\n");
381 perror("fork failed");
387 result = dup(my_pipe[1]);
389 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
392 result = dup(my_pipe[1]);
394 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
397 if (execvp(argv[0], (char *const *)argv) < 0) {
398 fprintf(stderr, "execvp failed\n"); /*Don't use d_msg_app2sd */
404 result = read(my_pipe[0], buf, FILENAME_MAX);
406 fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
410 ret_result = (char *)malloc(strlen(buf) + 1);
411 if (ret_result == NULL) {
412 app2ext_print("Malloc failed!\n");
415 memset(ret_result, '\0', strlen(buf) + 1);
416 memcpy(ret_result, buf, strlen(buf));
421 /*Note: Don't use any printf statement inside this function*/
422 char *_app2sd_find_free_device(void)
424 const char *argv[] = { "/sbin/losetup", "-f", NULL };
426 int my_pipe[2] = { 0, };
427 char buf[FILENAME_MAX+1] = { 0, };
428 char *ret_result = NULL;
430 if (pipe(my_pipe) < 0) {
431 fprintf(stderr, "Unable to create pipe\n");
437 perror("fork failed");
443 result = dup(my_pipe[1]);
445 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
448 result = dup(my_pipe[1]);
450 fprintf(stderr, "dup failed %d....%s\n", errno, strerror(errno));
453 if (execvp(argv[0], (char *const *)argv) < 0) {
454 fprintf(stderr, "execvp failed\n"); /*Don't use d_msg_app2sd */
460 result = read(my_pipe[0], buf, FILENAME_MAX);
462 fprintf(stderr, "read failed %d....%s\n", errno, strerror(errno));
466 ret_result = (char *)malloc(strlen(buf) + 1);
467 if (ret_result == NULL) {
468 app2ext_print("Malloc failed!\n");
471 memset(ret_result, '\0', strlen(buf) + 1);
472 memcpy(ret_result, buf, strlen(buf));
477 /*@_app2sd_generate_password
478 * This is a simple password generator
479 * return: On success, it will return the password, else NULL.
481 char *_app2sd_generate_password(const char *pkgid)
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;
489 int appname_len = strlen(pkgid);
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");
498 memset((void *)ret_result, '\0', PASSWD_LEN+1);
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];
506 passwd[i+2] = set[char_2];
510 app2ext_print("Password is %s\n", passwd);
511 memcpy(ret_result, passwd, PASSWD_LEN+1);
515 /*@_app2sd_setup_path
516 * change smack label given groupid
517 * return: On success, it will return the password, else NULL.
519 int _app2sd_setup_path(const char *pkgid, const char *dirpath,
520 int apppathtype, const char *groupid)
525 int (*perm_app_setup_path)(const char*, const char*, int, ...) = NULL;
527 if (pkgid == NULL || dirpath == NULL)
530 handle = dlopen(LIB_PRIVILEGE_CONTROL, RTLD_LAZY | RTLD_GLOBAL);
532 app2ext_print( "setup path: dlopen() failed. [%s]", dlerror());
536 perm_app_setup_path = dlsym(handle, "perm_app_setup_path");
538 if ((errmsg != NULL) || (perm_app_setup_path == NULL)) {
539 app2ext_print( "setup path: dlsym() failed. [%s]", errmsg);
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);
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);