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.
26 #include <storage-internal.h>
28 #include "app2sd_internals.h"
31 #define ASCII_PASSWD_CHAR 93
34 ########### Internal APIs ##################
37 /*Note: Don't use any printf statement inside this function*/
38 /*This function is similar to Linux's "system()" for executing a process.*/
39 int _xsystem(const char *argv[])
43 char err_buf[1024] = {0,};
48 perror("fork failed");
52 strerror_r(errno, err_buf, sizeof(err_buf));
53 if (execvp(argv[0], (char *const *)argv) < 0)
54 fprintf(stderr, "execvp failed %d....%s\n",
61 if (waitpid(pid, &status, 0) == -1) {
62 perror("waitpid failed");
65 if (WIFSIGNALED(status)) {
69 if (!WIFEXITED(status)) {
70 /* shouldn't happen */
71 perror("should not happen");
74 return WEXITSTATUS(status);
79 * This function checks and returns MMC status
81 int _app2sd_check_mmc_status(char **sdpath)
85 char *sd_mount_path = NULL;
87 ret = storage_get_primary_sdcard(&storage_id, &sd_mount_path);
88 if (ret != STORAGE_ERROR_NONE) {
89 _E("failed to get primary sdcard (%d)", ret);
92 return APP2EXT_ERROR_MMC_STATUS;
95 _D("primary sdcard: id(%d), mount_path(%s)",
96 storage_id, sd_mount_path);
97 *sdpath = sd_mount_path;
98 return APP2EXT_SUCCESS;
101 _E("there is no primary sdcard");
105 return APP2EXT_ERROR_MMC_STATUS;
109 * This function returns the available free memory in the SD Card.
110 * param [in]: sd_path: This is sd card access path.
111 * param [out]: free_mem: Result will be available in this.
112 * User has to pass valid memory address.
113 * return: On success, it will return 0.
114 * Else, appropriate error no will be returned.
116 int _app2sd_get_available_free_memory(char *mmc_path, int *free_mem)
120 unsigned long long temp = 0;
122 if (mmc_path == NULL || free_mem == NULL) {
123 _E("invalid input parameter");
127 memset((void *)&buf, '\0', sizeof(struct statvfs));
129 ret = statvfs(mmc_path, &buf);
131 _E("unable to get SD Card memory information");
132 return APP2EXT_ERROR_MMC_INFORMATION;
135 temp = (unsigned long long)buf.f_bsize*buf.f_bavail;
136 *free_mem = (int)(temp/(1024*1024));
141 void _app2sd_delete_symlink(const char *dirname)
146 struct dirent *er = NULL;
147 char abs_filename[FILENAME_MAX] = { 0, };
149 _D("start clean_symlink [%s]", dirname);
151 dp = opendir(dirname);
153 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
154 char mmc_path[PATH_MAX] = {0};
156 if (!strcmp(ep.d_name, ".") || !strcmp(ep.d_name, ".."))
159 /*get realpath find symlink to ".mmc" and unlink it*/
160 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep.d_name);
161 char *path = realpath(abs_filename, mmc_path);
163 _E("realpath failed");
165 if (strstr(mmc_path, ".mmc")) {
166 _E("force unlink [%s]", abs_filename);
167 if (unlink(abs_filename)) {
169 _W("Unable to access file %s", abs_filename);
171 _E("Unable to delete %s", abs_filename);
178 /*delete ".mmc" folder*/
179 snprintf(abs_filename, FILENAME_MAX, "%s/.mmc", dirname);
180 ret = remove(abs_filename);
184 _E("couldn't open the directory[%s]", dirname);
187 _D("finish clean_symlink");
190 int _app2sd_copy_dir(const char *src, const char *dest)
192 int ret = APP2EXT_SUCCESS;
194 const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
196 /* check existence before copy */
201 if (errno == ENOENT) {
202 _W("src(%s) not exist, skip!", src);
205 _E("failed to open src(%s) dir, errno(%d)", errno);
206 return APP2EXT_ERROR_ACCESS_FILE;
214 if (errno == ENOENT) {
215 _E("dest(%s) not exist, failed!", dest);
216 return APP2EXT_ERROR_ACCESS_FILE;
218 _E("failed to open dest(%s) dir, errno(%d)", errno);
219 return APP2EXT_ERROR_ACCESS_FILE;
223 ret = _xsystem(argv_bin);
225 _E("failed to copy dir, errno(%d)", errno);
226 return APP2EXT_ERROR_ACCESS_FILE;
231 int _app2sd_rename_dir(const char *old_name, const char *new_name)
233 int ret = APP2EXT_SUCCESS;
234 const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
235 ret = _xsystem(argv_bin);
237 _E("mv/rename fail");
238 return APP2EXT_ERROR_ACCESS_FILE;
243 unsigned long long _app2sd_calculate_dir_size(char *dirname)
245 static unsigned long long total = 0;
248 struct dirent *er = NULL;
249 char abs_filename[FILENAME_MAX] = { 0, };;
251 dp = opendir(dirname);
253 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
254 struct stat stFileInfo;
256 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
259 if (stat(abs_filename, &stFileInfo) < 0)
260 perror(abs_filename);
262 total += stFileInfo.st_size;
264 if (S_ISDIR(stFileInfo.st_mode)) {
265 if (strcmp(ep.d_name, ".")
266 && strcmp(ep.d_name, "..")) {
267 _app2sd_calculate_dir_size
277 _E("error in opening directory");
282 unsigned long long _app2sd_calculate_file_size(const char *filename)
284 struct stat stFileInfo;
285 _D("calculating file size for (%s)", filename);
287 if (stat(filename, &stFileInfo) < 0) {
291 return stFileInfo.st_size;
294 /*Note: Don't use any printf statement inside this function*/
295 char *_app2sd_encrypt_device(const char *device,
296 const char *loopback_device, char *passwd)
298 const char *argv[] = { "/sbin/losetup", device,
299 loopback_device, NULL };
301 int my_pipe[2] = { 0, };
302 char buf[FILENAME_MAX] = { 0, };
303 char *ret_result = NULL;
305 char err_buf[1024] = { 0,};
307 if (pipe(my_pipe) < 0) {
308 fprintf(stderr, "Unable to create pipe\n");
314 perror("fork failed");
320 result = dup(my_pipe[1]);
322 strerror_r(errno, err_buf, sizeof(err_buf));
323 fprintf(stderr, "dup failed %d....%s\n",
327 result = dup(my_pipe[1]);
329 strerror_r(errno, err_buf, sizeof(err_buf));
330 fprintf(stderr, "dup failed %d....%s\n",
334 if (execvp(argv[0], (char *const *)argv) < 0) {
335 strerror_r(errno, err_buf, sizeof(err_buf));
336 fprintf(stderr, "execvp failed %d....%s\n",
337 errno, err_buf); /*Don't use d_msg_app2sd */
343 result = read(my_pipe[0], buf, FILENAME_MAX);
345 strerror_r(errno, err_buf, sizeof(err_buf));
346 fprintf(stderr, "read failed %d....%s\n",
352 ret_result = (char *)malloc(strlen(buf) + 1);
353 if (ret_result == NULL) {
357 memset(ret_result, '\0', strlen(buf) + 1);
358 memcpy(ret_result, buf, strlen(buf));
363 /*Note: Don't use any printf statement inside this function*/
364 char *_app2sd_detach_loop_device(const char *device)
366 const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
368 int my_pipe[2] = { 0, };
369 char buf[FILENAME_MAX] = { 0, };
370 char *ret_result = NULL;
372 char err_buf[1024] = {0,};
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 strerror_r(errno, err_buf, sizeof(err_buf));
390 fprintf(stderr, "dup failed %d....%s\n",
394 result = dup(my_pipe[1]);
396 strerror_r(errno, err_buf, sizeof(err_buf));
397 fprintf(stderr, "dup failed %d....%s\n",
401 if (execvp(argv[0], (char *const *)argv) < 0) {
402 fprintf(stderr, "execvp failed\n");
403 /* Don't use d_msg_app2sd */
409 result = read(my_pipe[0], buf, FILENAME_MAX);
411 strerror_r(errno, err_buf, sizeof(err_buf));
412 fprintf(stderr, "read failed %d....%s\n",
418 ret_result = (char *)malloc(strlen(buf) + 1);
419 if (ret_result == NULL) {
423 memset(ret_result, '\0', strlen(buf) + 1);
424 memcpy(ret_result, buf, strlen(buf));
429 /* Note: Don't use any printf statement inside this function*/
430 char *_app2sd_find_associated_device(const char *loopback_device)
432 const char *argv[] = { "/sbin/losetup", "-a", NULL };
434 int my_pipe[2] = { 0, };
435 char buf[FILENAME_MAX] = { 0, };
436 char *ret_result_temp = NULL;
437 char *ret_result = NULL;
439 char *save_str = NULL;
441 char err_buf[1024] = {0,};
443 if (pipe(my_pipe) < 0) {
444 fprintf(stderr, "Unable to create pipe\n");
450 perror("fork failed");
456 result = dup(my_pipe[1]);
458 strerror_r(errno, err_buf, sizeof(err_buf));
459 fprintf(stderr, "dup failed %d....%s\n",
463 result = dup(my_pipe[1]);
465 strerror_r(errno, err_buf, sizeof(err_buf));
466 fprintf(stderr, "dup failed %d....%s\n",
470 if (execvp(argv[0], (char *const *)argv) < 0) {
471 fprintf(stderr, "execvp failed\n");
472 /* Don't use d_msg_app2sd */
478 result = read(my_pipe[0], buf, FILENAME_MAX);
480 strerror_r(errno, err_buf, sizeof(err_buf));
481 fprintf(stderr, "read failed %d....%s\n",
487 ret_result_temp = (char *)malloc(strlen(buf) + 1);
488 if (ret_result_temp == NULL) {
492 memset(ret_result_temp, '\0', strlen(buf) + 1);
493 memcpy(ret_result_temp, buf, strlen(buf));
495 line = strtok_r(ret_result_temp, "\n", &save_str);
497 if (strstr(line, loopback_device) != NULL) {
498 _D("found: (%s)", line);
500 _D("duplicated device");
502 ret_result = strdup(line);
504 line = strtok_r(NULL, "\n", &save_str);
506 free(ret_result_temp);
511 /*Note: Don't use any printf statement inside this function*/
512 char *_app2sd_find_free_device(void)
514 const char *argv[] = { "/sbin/losetup", "-f", NULL };
516 int my_pipe[2] = { 0, };
517 char buf[FILENAME_MAX + 1] = { 0, };
518 char *ret_result = NULL;
520 char err_buf[1024] = {0,};
522 if (pipe(my_pipe) < 0) {
523 fprintf(stderr, "Unable to create pipe\n");
529 perror("fork failed");
535 result = dup(my_pipe[1]);
537 strerror_r(errno, err_buf, sizeof(err_buf));
538 fprintf(stderr, "dup failed %d....%s\n",
542 result = dup(my_pipe[1]);
544 strerror_r(errno, err_buf, sizeof(err_buf));
545 fprintf(stderr, "dup failed %d....%s\n",
549 if (execvp(argv[0], (char *const *)argv) < 0) {
550 fprintf(stderr, "execvp failed\n");
551 /* Don't use d_msg_app2sd */
557 result = read(my_pipe[0], buf, FILENAME_MAX);
559 strerror_r(errno, err_buf, sizeof(err_buf));
560 fprintf(stderr, "read failed %d....%s\n",
566 ret_result = (char *)malloc(strlen(buf) + 1);
567 if (ret_result == NULL) {
571 memset(ret_result, '\0', strlen(buf) + 1);
572 memcpy(ret_result, buf, strlen(buf));
578 * This is a simple password generator
579 * return: On success, it will return the password, else NULL.
581 char *_app2sd_generate_password(const char *pkgid)
583 char passwd[PASSWD_LEN + 1] = { 0, };
584 char *ret_result = NULL;
585 char set[ASCII_PASSWD_CHAR + 1] =
586 "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
587 "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
588 unsigned char char_1;
589 unsigned char char_2;
591 int appname_len = strlen(pkgid);
595 /* length of the password */
596 ret_result = (char *)malloc(PASSWD_LEN + 1);
597 if (NULL == ret_result) {
598 _E("unable to allocate memory");
601 memset((void *)ret_result, '\0', PASSWD_LEN + 1);
603 while (i < PASSWD_LEN) {
606 char_1 = (rand_r(&seed) + pkgid[j]) % ASCII_PASSWD_CHAR;
607 char_2 = rand_r(&seed) % ASCII_PASSWD_CHAR;
608 passwd[i] = set[char_1];
610 passwd[i + 1] = set[((pkgid[j]) * 2) % ASCII_PASSWD_CHAR];
611 if (i < PASSWD_LEN - 3)
612 passwd[i + 2] = set[char_2];
616 memcpy(ret_result, passwd, PASSWD_LEN + 1);
621 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
622 int _app2sd_check_is_luks_device(const char *device_path)
625 int result = 1; /* default: luks format */
626 const char *argv_bin[] = { "/sbin/cryptsetup", "isLuks", device_path };
627 ret = _xsystem(argv_bin);
629 _E("there was errot to check isLuks");
631 if (ret == 1) /* legacy format */
634 _D("ret(%d), result(%d)", ret, result);