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 dp = opendir(dirname);
151 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
152 char mmc_path[PATH_MAX] = {0};
154 if (!strcmp(ep.d_name, ".") || !strcmp(ep.d_name, ".."))
157 /*get realpath find symlink to ".mmc" and unlink it*/
158 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep.d_name);
159 char *path = realpath(abs_filename, mmc_path);
161 _E("realpath failed");
163 if (strstr(mmc_path, ".mmc")) {
164 _E("force unlink [%s]", abs_filename);
165 if (unlink(abs_filename)) {
167 _W("Unable to access file %s", abs_filename);
169 _E("Unable to delete %s", abs_filename);
176 /*delete ".mmc" folder*/
177 snprintf(abs_filename, FILENAME_MAX, "%s/.mmc", dirname);
178 ret = remove(abs_filename);
184 int _app2sd_copy_dir(const char *src, const char *dest)
186 int ret = APP2EXT_SUCCESS;
188 const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
190 /* check existence before copy */
195 if (errno == ENOENT) {
196 _W("src(%s) not exist, skip!", src);
199 _E("failed to open src(%s) dir, errno(%d)", errno);
200 return APP2EXT_ERROR_ACCESS_FILE;
208 if (errno == ENOENT) {
209 _E("dest(%s) not exist, failed!", dest);
210 return APP2EXT_ERROR_ACCESS_FILE;
212 _E("failed to open dest(%s) dir, errno(%d)", errno);
213 return APP2EXT_ERROR_ACCESS_FILE;
217 ret = _xsystem(argv_bin);
219 _E("failed to copy dir, errno(%d)", errno);
220 return APP2EXT_ERROR_ACCESS_FILE;
225 int _app2sd_rename_dir(const char *old_name, const char *new_name)
227 int ret = APP2EXT_SUCCESS;
228 const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
229 ret = _xsystem(argv_bin);
231 _E("mv/rename fail");
232 return APP2EXT_ERROR_ACCESS_FILE;
237 unsigned long long _app2sd_calculate_dir_size(char *dirname)
239 static unsigned long long total = 0;
242 struct dirent *er = NULL;
243 char abs_filename[FILENAME_MAX] = { 0, };;
245 dp = opendir(dirname);
247 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
248 struct stat stFileInfo;
250 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
253 if (stat(abs_filename, &stFileInfo) < 0)
254 perror(abs_filename);
256 total += stFileInfo.st_size;
258 if (S_ISDIR(stFileInfo.st_mode)) {
259 if (strcmp(ep.d_name, ".")
260 && strcmp(ep.d_name, "..")) {
261 _app2sd_calculate_dir_size
271 _E("error in opening directory");
276 unsigned long long _app2sd_calculate_file_size(const char *filename)
278 struct stat stFileInfo;
279 _D("calculating file size for (%s)", filename);
281 if (stat(filename, &stFileInfo) < 0) {
285 return stFileInfo.st_size;
288 /*Note: Don't use any printf statement inside this function*/
289 char *_app2sd_encrypt_device(const char *device,
290 const char *loopback_device, char *passwd)
292 const char *argv[] = { "/sbin/losetup", device,
293 loopback_device, NULL };
295 int my_pipe[2] = { 0, };
296 char buf[FILENAME_MAX] = { 0, };
297 char *ret_result = NULL;
299 char err_buf[1024] = { 0,};
301 if (pipe(my_pipe) < 0) {
302 fprintf(stderr, "Unable to create pipe\n");
308 perror("fork failed");
314 result = dup(my_pipe[1]);
316 strerror_r(errno, err_buf, sizeof(err_buf));
317 fprintf(stderr, "dup failed %d....%s\n",
321 result = dup(my_pipe[1]);
323 strerror_r(errno, err_buf, sizeof(err_buf));
324 fprintf(stderr, "dup failed %d....%s\n",
328 if (execvp(argv[0], (char *const *)argv) < 0) {
329 strerror_r(errno, err_buf, sizeof(err_buf));
330 fprintf(stderr, "execvp failed %d....%s\n",
331 errno, err_buf); /*Don't use d_msg_app2sd */
337 result = read(my_pipe[0], buf, FILENAME_MAX);
339 strerror_r(errno, err_buf, sizeof(err_buf));
340 fprintf(stderr, "read failed %d....%s\n",
346 ret_result = (char *)malloc(strlen(buf) + 1);
347 if (ret_result == NULL) {
351 memset(ret_result, '\0', strlen(buf) + 1);
352 memcpy(ret_result, buf, strlen(buf));
357 /*Note: Don't use any printf statement inside this function*/
358 char *_app2sd_detach_loop_device(const char *device)
360 const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
362 int my_pipe[2] = { 0, };
363 char buf[FILENAME_MAX] = { 0, };
364 char *ret_result = NULL;
366 char err_buf[1024] = {0,};
368 if (pipe(my_pipe) < 0) {
369 fprintf(stderr, "Unable to create pipe\n");
375 perror("fork failed");
381 result = dup(my_pipe[1]);
383 strerror_r(errno, err_buf, sizeof(err_buf));
384 fprintf(stderr, "dup failed %d....%s\n",
388 result = dup(my_pipe[1]);
390 strerror_r(errno, err_buf, sizeof(err_buf));
391 fprintf(stderr, "dup failed %d....%s\n",
395 if (execvp(argv[0], (char *const *)argv) < 0) {
396 fprintf(stderr, "execvp failed\n");
397 /* Don't use d_msg_app2sd */
403 result = read(my_pipe[0], buf, FILENAME_MAX);
405 strerror_r(errno, err_buf, sizeof(err_buf));
406 fprintf(stderr, "read failed %d....%s\n",
412 ret_result = (char *)malloc(strlen(buf) + 1);
413 if (ret_result == NULL) {
417 memset(ret_result, '\0', strlen(buf) + 1);
418 memcpy(ret_result, buf, strlen(buf));
423 /* Note: Don't use any printf statement inside this function*/
424 char *_app2sd_find_associated_device(const char *loopback_device)
426 const char *argv[] = { "/sbin/losetup", "-a", NULL };
428 int my_pipe[2] = { 0, };
429 char buf[FILENAME_MAX] = { 0, };
430 char *ret_result_temp = NULL;
431 char *ret_result = NULL;
433 char *save_str = NULL;
435 char err_buf[1024] = {0,};
437 if (pipe(my_pipe) < 0) {
438 fprintf(stderr, "Unable to create pipe\n");
444 perror("fork failed");
450 result = dup(my_pipe[1]);
452 strerror_r(errno, err_buf, sizeof(err_buf));
453 fprintf(stderr, "dup failed %d....%s\n",
457 result = dup(my_pipe[1]);
459 strerror_r(errno, err_buf, sizeof(err_buf));
460 fprintf(stderr, "dup failed %d....%s\n",
464 if (execvp(argv[0], (char *const *)argv) < 0) {
465 fprintf(stderr, "execvp failed\n");
466 /* Don't use d_msg_app2sd */
472 result = read(my_pipe[0], buf, FILENAME_MAX);
474 strerror_r(errno, err_buf, sizeof(err_buf));
475 fprintf(stderr, "read failed %d....%s\n",
481 ret_result_temp = (char *)malloc(strlen(buf) + 1);
482 if (ret_result_temp == NULL) {
486 memset(ret_result_temp, '\0', strlen(buf) + 1);
487 memcpy(ret_result_temp, buf, strlen(buf));
489 line = strtok_r(ret_result_temp, "\n", &save_str);
491 if (strstr(line, loopback_device) != NULL) {
492 _D("found: (%s)", line);
494 _D("duplicated device");
496 ret_result = strdup(line);
498 line = strtok_r(NULL, "\n", &save_str);
500 free(ret_result_temp);
505 /*Note: Don't use any printf statement inside this function*/
506 char *_app2sd_find_free_device(void)
508 const char *argv[] = { "/sbin/losetup", "-f", NULL };
510 int my_pipe[2] = { 0, };
511 char buf[FILENAME_MAX + 1] = { 0, };
512 char *ret_result = NULL;
514 char err_buf[1024] = {0,};
516 if (pipe(my_pipe) < 0) {
517 fprintf(stderr, "Unable to create pipe\n");
523 perror("fork failed");
529 result = dup(my_pipe[1]);
531 strerror_r(errno, err_buf, sizeof(err_buf));
532 fprintf(stderr, "dup failed %d....%s\n",
536 result = dup(my_pipe[1]);
538 strerror_r(errno, err_buf, sizeof(err_buf));
539 fprintf(stderr, "dup failed %d....%s\n",
543 if (execvp(argv[0], (char *const *)argv) < 0) {
544 fprintf(stderr, "execvp failed\n");
545 /* Don't use d_msg_app2sd */
551 result = read(my_pipe[0], buf, FILENAME_MAX);
553 strerror_r(errno, err_buf, sizeof(err_buf));
554 fprintf(stderr, "read failed %d....%s\n",
560 ret_result = (char *)malloc(strlen(buf) + 1);
561 if (ret_result == NULL) {
565 memset(ret_result, '\0', strlen(buf) + 1);
566 memcpy(ret_result, buf, strlen(buf));
572 * This is a simple password generator
573 * return: On success, it will return the password, else NULL.
575 char *_app2sd_generate_password(const char *pkgid)
577 char passwd[PASSWD_LEN + 1] = { 0, };
578 char *ret_result = NULL;
579 char set[ASCII_PASSWD_CHAR + 1] =
580 "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
581 "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
582 unsigned char char_1;
583 unsigned char char_2;
585 int appname_len = strlen(pkgid);
589 /* length of the password */
590 ret_result = (char *)malloc(PASSWD_LEN + 1);
591 if (NULL == ret_result) {
592 _E("unable to allocate memory");
595 memset((void *)ret_result, '\0', PASSWD_LEN + 1);
597 while (i < PASSWD_LEN) {
600 char_1 = (rand_r(&seed) + pkgid[j]) % ASCII_PASSWD_CHAR;
601 char_2 = rand_r(&seed) % ASCII_PASSWD_CHAR;
602 passwd[i] = set[char_1];
604 passwd[i + 1] = set[((pkgid[j]) * 2) % ASCII_PASSWD_CHAR];
605 if (i < PASSWD_LEN - 3)
606 passwd[i + 2] = set[char_2];
610 memcpy(ret_result, passwd, PASSWD_LEN + 1);
615 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
616 int _app2sd_check_is_luks_device(const char *device_path)
619 int result = 1; /* default: luks format */
620 const char *argv_bin[] = { "/sbin/cryptsetup", "isLuks", device_path };
621 ret = _xsystem(argv_bin);
623 _E("there was errot to check isLuks");
625 if (ret == 1) /* legacy format */
628 _D("ret(%d), result(%d)", ret, result);