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)
145 struct dirent *ep = NULL;
146 char abs_filename[FILENAME_MAX] = { 0, };
148 _D("start clean_symlink [%s]", dirname);
150 dp = opendir(dirname);
152 while ((ep = readdir(dp)) != NULL) {
153 char mmc_path[PATH_MAX] = {0};
155 if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
158 /*get realpath find symlink to ".mmc" and unlink it*/
159 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep->d_name);
160 char *path = realpath(abs_filename, mmc_path);
162 _E("realpath failed");
164 if (strstr(mmc_path, ".mmc")) {
165 _E("force unlink [%s]", abs_filename);
166 if (unlink(abs_filename)) {
168 _W("Unable to access file %s", abs_filename);
170 _E("Unable to delete %s", abs_filename);
177 /*delete ".mmc" folder*/
178 snprintf(abs_filename, FILENAME_MAX, "%s/.mmc", dirname);
179 ret = remove(abs_filename);
183 _E("couldn't open the directory[%s]", dirname);
186 _D("finish clean_symlink");
189 int _app2sd_copy_dir(const char *src, const char *dest)
191 int ret = APP2EXT_SUCCESS;
193 const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
195 /* check existence before copy */
200 if (errno == ENOENT) {
201 _W("src(%s) not exist, skip!", src);
204 _E("failed to open src(%s) dir, errno(%d)", errno);
205 return APP2EXT_ERROR_MOVE;
213 if (errno == ENOENT) {
214 _E("dest(%s) not exist, failed!", dest);
215 return APP2EXT_ERROR_MOVE;
217 _E("failed to open dest(%s) dir, errno(%d)", errno);
218 return APP2EXT_ERROR_MOVE;
222 ret = _xsystem(argv_bin);
224 _E("failed to copy dir, errno(%d)", errno);
225 return APP2EXT_ERROR_MOVE;
230 int _app2sd_rename_dir(const char *old_name, const char *new_name)
232 int ret = APP2EXT_SUCCESS;
233 const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
234 ret = _xsystem(argv_bin);
236 _E("mv/rename fail");
237 return APP2EXT_ERROR_MOVE;
242 unsigned long long _app2sd_calculate_dir_size(char *dirname)
244 static unsigned long long total = 0;
246 struct dirent *ep = NULL;
247 char abs_filename[FILENAME_MAX] = { 0, };;
249 dp = opendir(dirname);
251 while ((ep = readdir(dp)) != NULL) {
252 struct stat stFileInfo;
254 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
257 if (stat(abs_filename, &stFileInfo) < 0)
258 perror(abs_filename);
260 total += stFileInfo.st_size;
262 if (S_ISDIR(stFileInfo.st_mode)) {
263 if (strcmp(ep->d_name, ".")
264 && strcmp(ep->d_name, "..")) {
265 _app2sd_calculate_dir_size
275 _E("error in opening directory");
280 unsigned long long _app2sd_calculate_file_size(const char *filename)
282 struct stat stFileInfo;
283 _D("calculating file size for (%s)", filename);
285 if (stat(filename, &stFileInfo) < 0) {
289 return stFileInfo.st_size;
292 /*Note: Don't use any printf statement inside this function*/
293 char *_app2sd_encrypt_device(const char *device,
294 const char *loopback_device, char *passwd)
296 const char *argv[] = { "/sbin/losetup", device,
297 loopback_device, NULL };
299 int my_pipe[2] = { 0, };
300 char buf[FILENAME_MAX] = { 0, };
301 char *ret_result = NULL;
303 char err_buf[1024] = { 0,};
305 if (pipe(my_pipe) < 0) {
306 fprintf(stderr, "Unable to create pipe\n");
312 perror("fork failed");
318 result = dup(my_pipe[1]);
320 strerror_r(errno, err_buf, sizeof(err_buf));
321 fprintf(stderr, "dup failed %d....%s\n",
325 result = dup(my_pipe[1]);
327 strerror_r(errno, err_buf, sizeof(err_buf));
328 fprintf(stderr, "dup failed %d....%s\n",
332 if (execvp(argv[0], (char *const *)argv) < 0) {
333 strerror_r(errno, err_buf, sizeof(err_buf));
334 fprintf(stderr, "execvp failed %d....%s\n",
335 errno, err_buf); /*Don't use d_msg_app2sd */
341 result = read(my_pipe[0], buf, FILENAME_MAX);
343 strerror_r(errno, err_buf, sizeof(err_buf));
344 fprintf(stderr, "read failed %d....%s\n",
350 ret_result = (char *)malloc(strlen(buf) + 1);
351 if (ret_result == NULL) {
355 memset(ret_result, '\0', strlen(buf) + 1);
356 memcpy(ret_result, buf, strlen(buf));
361 /*Note: Don't use any printf statement inside this function*/
362 char *_app2sd_detach_loop_device(const char *device)
364 const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
366 int my_pipe[2] = { 0, };
367 char buf[FILENAME_MAX] = { 0, };
368 char *ret_result = NULL;
370 char err_buf[1024] = {0,};
372 if (pipe(my_pipe) < 0) {
373 fprintf(stderr, "Unable to create pipe\n");
379 perror("fork failed");
385 result = dup(my_pipe[1]);
387 strerror_r(errno, err_buf, sizeof(err_buf));
388 fprintf(stderr, "dup failed %d....%s\n",
392 result = dup(my_pipe[1]);
394 strerror_r(errno, err_buf, sizeof(err_buf));
395 fprintf(stderr, "dup failed %d....%s\n",
399 if (execvp(argv[0], (char *const *)argv) < 0) {
400 fprintf(stderr, "execvp failed\n");
401 /* Don't use d_msg_app2sd */
407 result = read(my_pipe[0], buf, FILENAME_MAX);
409 strerror_r(errno, err_buf, sizeof(err_buf));
410 fprintf(stderr, "read failed %d....%s\n",
416 ret_result = (char *)malloc(strlen(buf) + 1);
417 if (ret_result == NULL) {
421 memset(ret_result, '\0', strlen(buf) + 1);
422 memcpy(ret_result, buf, strlen(buf));
427 /* Note: Don't use any printf statement inside this function*/
428 char *_app2sd_find_associated_device(const char *loopback_device)
430 const char *argv[] = { "/sbin/losetup", "-a", NULL };
432 int my_pipe[2] = { 0, };
433 char buf[FILENAME_MAX] = { 0, };
434 char *ret_result_temp = NULL;
435 char *ret_result = NULL;
437 char *save_str = NULL;
439 char err_buf[1024] = {0,};
441 if (pipe(my_pipe) < 0) {
442 fprintf(stderr, "Unable to create pipe\n");
448 perror("fork failed");
454 result = dup(my_pipe[1]);
456 strerror_r(errno, err_buf, sizeof(err_buf));
457 fprintf(stderr, "dup failed %d....%s\n",
461 result = dup(my_pipe[1]);
463 strerror_r(errno, err_buf, sizeof(err_buf));
464 fprintf(stderr, "dup failed %d....%s\n",
468 if (execvp(argv[0], (char *const *)argv) < 0) {
469 fprintf(stderr, "execvp failed\n");
470 /* Don't use d_msg_app2sd */
476 result = read(my_pipe[0], buf, FILENAME_MAX);
478 strerror_r(errno, err_buf, sizeof(err_buf));
479 fprintf(stderr, "read failed %d....%s\n",
485 ret_result_temp = (char *)malloc(strlen(buf) + 1);
486 if (ret_result_temp == NULL) {
490 memset(ret_result_temp, '\0', strlen(buf) + 1);
491 memcpy(ret_result_temp, buf, strlen(buf));
493 line = strtok_r(ret_result_temp, "\n", &save_str);
495 if (strstr(line, loopback_device) != NULL) {
496 _D("found: (%s)", line);
498 _D("duplicated device");
500 ret_result = strdup(line);
502 line = strtok_r(NULL, "\n", &save_str);
504 free(ret_result_temp);
509 /*Note: Don't use any printf statement inside this function*/
510 char *_app2sd_find_free_device(void)
512 const char *argv[] = { "/sbin/losetup", "-f", NULL };
514 int my_pipe[2] = { 0, };
515 char buf[FILENAME_MAX + 1] = { 0, };
516 char *ret_result = NULL;
518 char err_buf[1024] = {0,};
520 if (pipe(my_pipe) < 0) {
521 fprintf(stderr, "Unable to create pipe\n");
527 perror("fork failed");
533 result = dup(my_pipe[1]);
535 strerror_r(errno, err_buf, sizeof(err_buf));
536 fprintf(stderr, "dup failed %d....%s\n",
540 result = dup(my_pipe[1]);
542 strerror_r(errno, err_buf, sizeof(err_buf));
543 fprintf(stderr, "dup failed %d....%s\n",
547 if (execvp(argv[0], (char *const *)argv) < 0) {
548 fprintf(stderr, "execvp failed\n");
549 /* Don't use d_msg_app2sd */
555 result = read(my_pipe[0], buf, FILENAME_MAX);
557 strerror_r(errno, err_buf, sizeof(err_buf));
558 fprintf(stderr, "read failed %d....%s\n",
564 ret_result = (char *)malloc(strlen(buf) + 1);
565 if (ret_result == NULL) {
569 memset(ret_result, '\0', strlen(buf) + 1);
570 memcpy(ret_result, buf, strlen(buf));
576 * This is a simple password generator
577 * return: On success, it will return the password, else NULL.
579 char *_app2sd_generate_password(const char *pkgid)
581 char passwd[PASSWD_LEN + 1] = { 0, };
582 char *ret_result = NULL;
583 char set[ASCII_PASSWD_CHAR + 1] =
584 "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
585 "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
586 unsigned char char_1;
587 unsigned char char_2;
589 int appname_len = strlen(pkgid);
593 /* length of the password */
594 ret_result = (char *)malloc(PASSWD_LEN + 1);
595 if (NULL == ret_result) {
596 _E("unable to allocate memory");
599 memset((void *)ret_result, '\0', PASSWD_LEN + 1);
601 while (i < PASSWD_LEN) {
604 char_1 = (rand_r(&seed) + pkgid[j]) % ASCII_PASSWD_CHAR;
605 char_2 = rand_r(&seed) % ASCII_PASSWD_CHAR;
606 passwd[i] = set[char_1];
608 passwd[i + 1] = set[((pkgid[j]) * 2) % ASCII_PASSWD_CHAR];
609 if (i < PASSWD_LEN - 3)
610 passwd[i + 2] = set[char_2];
614 memcpy(ret_result, passwd, PASSWD_LEN + 1);