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>
32 #include <sys/types.h>
37 #include <sys/statvfs.h>
41 #define ASCII_PASSWD_CHAR 93
44 ########### Internal APIs ##################
47 /*Note: Don't use any printf statement inside this function*/
48 /*This function is similar to Linux's "system()" for executing a process.*/
49 int _xsystem(const char *argv[])
53 char err_buf[1024] = {0,};
58 perror("fork failed");
62 strerror_r(errno, err_buf, sizeof(err_buf));
63 if (execvp(argv[0], (char *const *)argv) < 0) {
64 fprintf(stderr, "execvp failed %d....%s\n", errno, err_buf); /*Don't use d_msg_app2sd */
71 if (waitpid(pid, &status, 0) == -1) {
72 perror("waitpid failed");
75 if (WIFSIGNALED(status)) {
79 if (!WIFEXITED(status)) {
80 /* shouldn't happen */
81 perror("should not happen");
84 return WEXITSTATUS(status);
89 * @_app2sd_check_mmc_status
90 * This function checks and returns MMC status
92 /* TODO : another possible way ? */
93 int _app2sd_check_mmc_status(void)
97 fp1 = fopen("/etc/mtab", "r");
99 fprintf(stderr, "failed to open file\n");
100 _E("failed to open file /etc/mtab");
101 return APP2EXT_ERROR_MMC_STATUS;
103 while (fgets(line, 512, fp1) != NULL) {
104 if (strstr(line, MMC_PATH) != NULL) {
106 return APP2EXT_SUCCESS;
110 return APP2EXT_ERROR_MMC_STATUS;
114 * @_app2sd_get_available_free_memory
115 * This function returns the available free memory in the SD Card.
116 * param [in]: sd_path: This is sd card access path.
117 * param [out]: free_mem: Result will be available in this.
118 * User has to pass valid memory address.
119 * return: On success, it will return 0.
120 * Else, appropriate error no will be returned.
122 int _app2sd_get_available_free_memory(const char *sd_path, int *free_mem)
126 unsigned long long temp = 0;
128 if (sd_path == NULL || free_mem == NULL) {
129 _E("invalid input parameter");
133 memset((void *)&buf, '\0', sizeof(struct statvfs));
135 ret = statvfs(sd_path, &buf);
137 _E("unable to get SD Card memory information");
138 return APP2EXT_ERROR_MMC_INFORMATION;
141 temp = (unsigned long long)buf.f_bsize*buf.f_bavail;
142 *free_mem = (int)(temp/(1024*1024));
147 int _app2sd_delete_directory(const char *dirname)
151 struct dirent *er = NULL;
152 char abs_filename[FILENAME_MAX] = { 0, };
155 dp = opendir(dirname);
157 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
158 struct stat stFileInfo;
160 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
163 if (lstat(abs_filename, &stFileInfo) < 0) {
164 perror(abs_filename);
169 if (S_ISDIR(stFileInfo.st_mode)) {
170 if (strcmp(ep.d_name, ".")
171 && strcmp(ep.d_name, "..")) {
172 ret = _app2sd_delete_directory(abs_filename);
179 ret = remove(abs_filename);
187 ret = remove(dirname);
191 _E("couldn't open the directory[%s]", dirname);
196 void _app2sd_delete_symlink(const char *dirname)
201 struct dirent *er = NULL;
202 char abs_filename[FILENAME_MAX] = { 0, };
204 _D("start clean_symlink [%s]", dirname);
206 dp = opendir(dirname);
208 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
209 char mmc_path[PATH_MAX] = {0};
211 if (!strcmp(ep.d_name, ".") || !strcmp(ep.d_name, ".."))
214 /*get realpath find symlink to ".mmc" and unlink it*/
215 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep.d_name);
216 char *path = realpath(abs_filename, mmc_path);
218 _E("realpath failed");
221 if (strstr(mmc_path,".mmc")) {
222 _E("force unlink [%s]", abs_filename);
223 if (unlink(abs_filename)) {
224 if (errno == ENOENT) {
225 _E("Unable to access file %s", abs_filename);
227 _E("Unable to delete %s", abs_filename);
235 /*delete ".mmc" folder*/
236 snprintf(abs_filename, FILENAME_MAX, "%s/.mmc", dirname);
237 ret = remove(abs_filename);
242 _E("couldn't open the directory[%s]", dirname);
245 _D("finish clean_symlink");
248 int _app2sd_copy_dir(const char *src, const char *dest)
250 int ret = APP2EXT_SUCCESS;
251 const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
252 ret = _xsystem(argv_bin);
255 return APP2EXT_ERROR_MOVE;
260 int _app2sd_rename_dir(const char *old_name, const char *new_name)
262 int ret = APP2EXT_SUCCESS;
263 const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
264 ret = _xsystem(argv_bin);
266 _E("mv/rename fail");
267 return APP2EXT_ERROR_MOVE;
272 unsigned long long _app2sd_calculate_dir_size(char *dirname)
274 static unsigned long long total = 0;
277 struct dirent *er = NULL;
278 char abs_filename[FILENAME_MAX] = { 0, };;
280 dp = opendir(dirname);
282 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
283 struct stat stFileInfo;
285 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
288 if (stat(abs_filename, &stFileInfo) < 0)
289 perror(abs_filename);
291 total += stFileInfo.st_size;
293 if (S_ISDIR(stFileInfo.st_mode)) {
294 if (strcmp(ep.d_name, ".")
295 && strcmp(ep.d_name, "..")) {
296 _app2sd_calculate_dir_size
306 _E("error in opening directory");
311 unsigned long long _app2sd_calculate_file_size(const char *filename)
313 struct stat stFileInfo;
314 _D("calculating file size for (%s)", filename);
316 if (stat(filename, &stFileInfo) < 0) {
320 return stFileInfo.st_size;
323 /*Note: Don't use any printf statement inside this function*/
324 char *_app2sd_encrypt_device(const char *device,
325 const char *loopback_device, char *passwd)
327 /* TODO : change to dm-crypt */
329 { "/sbin/losetup", device, loopback_device, NULL };
331 int my_pipe[2] = { 0, };
332 char buf[FILENAME_MAX] = { 0, };
333 char *ret_result = NULL;
335 char err_buf[1024] = {0,};
337 if (pipe(my_pipe) < 0) {
338 fprintf(stderr, "Unable to create pipe\n");
344 perror("fork failed");
350 result = dup(my_pipe[1]);
352 strerror_r(errno, err_buf, sizeof(err_buf));
353 fprintf(stderr, "dup failed %d....%s\n",
357 result = dup(my_pipe[1]);
359 strerror_r(errno, err_buf, sizeof(err_buf));
360 fprintf(stderr, "dup failed %d....%s\n",
364 if (execvp(argv[0], (char *const *)argv) < 0) {
365 strerror_r(errno, err_buf, sizeof(err_buf));
366 fprintf(stderr, "execvp failed %d....%s\n",
367 errno, err_buf); /*Don't use d_msg_app2sd */
373 result = read(my_pipe[0], buf, FILENAME_MAX);
375 strerror_r(errno, err_buf, sizeof(err_buf));
376 fprintf(stderr, "read failed %d....%s\n",
382 ret_result = (char *)malloc(strlen(buf) + 1);
383 if (ret_result == NULL) {
387 memset(ret_result, '\0', strlen(buf) + 1);
388 memcpy(ret_result, buf, strlen(buf));
393 /*Note: Don't use any printf statement inside this function*/
394 char *_app2sd_detach_loop_device(const char *device)
396 const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
398 int my_pipe[2] = { 0, };
399 char buf[FILENAME_MAX] = { 0, };
400 char *ret_result = NULL;
402 char err_buf[1024] = {0,};
404 if (pipe(my_pipe) < 0) {
405 fprintf(stderr, "Unable to create pipe\n");
411 perror("fork failed");
417 result = dup(my_pipe[1]);
419 strerror_r(errno, err_buf, sizeof(err_buf));
420 fprintf(stderr, "dup failed %d....%s\n",
424 result = dup(my_pipe[1]);
426 strerror_r(errno, err_buf, sizeof(err_buf));
427 fprintf(stderr, "dup failed %d....%s\n",
431 if (execvp(argv[0], (char *const *)argv) < 0) {
432 fprintf(stderr, "execvp failed\n");
433 /* Don't use d_msg_app2sd */
439 result = read(my_pipe[0], buf, FILENAME_MAX);
441 strerror_r(errno, err_buf, sizeof(err_buf));
442 fprintf(stderr, "read failed %d....%s\n",
448 ret_result = (char *)malloc(strlen(buf) + 1);
449 if (ret_result == NULL) {
453 memset(ret_result, '\0', strlen(buf) + 1);
454 memcpy(ret_result, buf, strlen(buf));
459 /* Note: Don't use any printf statement inside this function*/
460 char *_app2sd_find_associated_device(const char *loopback_device)
462 const char *argv[] = { "/sbin/losetup", "-a", NULL };
464 int my_pipe[2] = { 0, };
465 char buf[FILENAME_MAX] = { 0, };
466 char *ret_result_temp = NULL;
467 char *ret_result = NULL;
469 char *save_str = NULL;
471 char err_buf[1024] = {0,};
473 if (pipe(my_pipe) < 0) {
474 fprintf(stderr, "Unable to create pipe\n");
480 perror("fork failed");
486 result = dup(my_pipe[1]);
488 strerror_r(errno, err_buf, sizeof(err_buf));
489 fprintf(stderr, "dup failed %d....%s\n",
493 result = dup(my_pipe[1]);
495 strerror_r(errno, err_buf, sizeof(err_buf));
496 fprintf(stderr, "dup failed %d....%s\n",
500 if (execvp(argv[0], (char *const *)argv) < 0) {
501 fprintf(stderr, "execvp failed\n");
502 /* Don't use d_msg_app2sd */
508 result = read(my_pipe[0], buf, FILENAME_MAX);
510 strerror_r(errno, err_buf, sizeof(err_buf));
511 fprintf(stderr, "read failed %d....%s\n",
517 ret_result_temp = (char *)malloc(strlen(buf) + 1);
518 if (ret_result_temp == NULL) {
522 memset(ret_result_temp, '\0', strlen(buf) + 1);
523 memcpy(ret_result_temp, buf, strlen(buf));
525 line = strtok_r(ret_result_temp, "\n", &save_str);
527 if (strstr(line, loopback_device) != NULL) {
528 _D("found: (%s)", line);
530 _D("duplicated device");
532 ret_result = strdup(line);
535 line = strtok_r(NULL, "\n", &save_str);
537 free(ret_result_temp);
542 /*Note: Don't use any printf statement inside this function*/
543 char *_app2sd_find_free_device(void)
545 const char *argv[] = { "/sbin/losetup", "-f", NULL };
547 int my_pipe[2] = { 0, };
548 char buf[FILENAME_MAX + 1] = { 0, };
549 char *ret_result = NULL;
551 char err_buf[1024] = {0,};
553 if (pipe(my_pipe) < 0) {
554 fprintf(stderr, "Unable to create pipe\n");
560 perror("fork failed");
566 result = dup(my_pipe[1]);
568 strerror_r(errno, err_buf, sizeof(err_buf));
569 fprintf(stderr, "dup failed %d....%s\n",
573 result = dup(my_pipe[1]);
575 strerror_r(errno, err_buf, sizeof(err_buf));
576 fprintf(stderr, "dup failed %d....%s\n",
580 if (execvp(argv[0], (char *const *)argv) < 0) {
581 fprintf(stderr, "execvp failed\n");
582 /* Don't use d_msg_app2sd */
588 result = read(my_pipe[0], buf, FILENAME_MAX);
590 strerror_r(errno, err_buf, sizeof(err_buf));
591 fprintf(stderr, "read failed %d....%s\n",
597 ret_result = (char *)malloc(strlen(buf) + 1);
598 if (ret_result == NULL) {
602 memset(ret_result, '\0', strlen(buf) + 1);
603 memcpy(ret_result, buf, strlen(buf));
608 /*@_app2sd_generate_password
609 * This is a simple password generator
610 * return: On success, it will return the password, else NULL.
612 char *_app2sd_generate_password(const char *pkgid)
614 char passwd[PASSWD_LEN+1] = { 0, };
615 char *ret_result = NULL;
616 char set[ASCII_PASSWD_CHAR+1] =
617 "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
618 "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
619 unsigned char char_1;
620 unsigned char char_2;
622 int appname_len = strlen(pkgid);
626 /* Length of the password */
627 ret_result = (char*)malloc(PASSWD_LEN + 1);
628 if (NULL == ret_result) {
629 _E("unable to allocate memory");
632 memset((void *)ret_result, '\0', PASSWD_LEN + 1);
634 while (i < PASSWD_LEN) {
636 char_1 = (rand_r(&seed) + pkgid[j--]) % ASCII_PASSWD_CHAR;
637 char_2 = rand_r(&seed) % ASCII_PASSWD_CHAR;
638 passwd[i] = set[char_1];
639 passwd[i + 1] = set[(pkgid[j--]) * 2];
640 if (i < PASSWD_LEN - 3)
641 passwd[i + 2] = set[char_2];
645 memcpy(ret_result, passwd, PASSWD_LEN + 1);