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.
27 #include "app2sd_internals.h"
30 #define ASCII_PASSWD_CHAR 93
33 ########### Internal APIs ##################
36 /*Note: Don't use any printf statement inside this function*/
37 /*This function is similar to Linux's "system()" for executing a process.*/
38 int _xsystem(const char *argv[])
42 char err_buf[1024] = {0,};
47 perror("fork failed");
51 strerror_r(errno, err_buf, sizeof(err_buf));
52 if (execvp(argv[0], (char *const *)argv) < 0)
53 fprintf(stderr, "execvp failed %d....%s\n",
60 if (waitpid(pid, &status, 0) == -1) {
61 perror("waitpid failed");
64 if (WIFSIGNALED(status)) {
68 if (!WIFEXITED(status)) {
69 /* shouldn't happen */
70 perror("should not happen");
73 return WEXITSTATUS(status);
78 * @_app2sd_check_mmc_status
79 * This function checks and returns MMC status
81 /* TODO : another possible way ? */
82 int _app2sd_check_mmc_status(void)
86 fp1 = fopen("/etc/mtab", "r");
88 fprintf(stderr, "failed to open file\n");
89 _E("failed to open file /etc/mtab");
90 return APP2EXT_ERROR_MMC_STATUS;
92 while (fgets(line, 512, fp1) != NULL) {
93 if (strstr(line, MMC_PATH) != NULL) {
95 return APP2EXT_SUCCESS;
99 return APP2EXT_ERROR_MMC_STATUS;
103 * @_app2sd_get_available_free_memory
104 * This function returns the available free memory in the SD Card.
105 * param [in]: sd_path: This is sd card access path.
106 * param [out]: free_mem: Result will be available in this.
107 * User has to pass valid memory address.
108 * return: On success, it will return 0.
109 * Else, appropriate error no will be returned.
111 int _app2sd_get_available_free_memory(const char *sd_path, int *free_mem)
115 unsigned long long temp = 0;
117 if (sd_path == NULL || free_mem == NULL) {
118 _E("invalid input parameter");
122 memset((void *)&buf, '\0', sizeof(struct statvfs));
124 ret = statvfs(sd_path, &buf);
126 _E("unable to get SD Card memory information");
127 return APP2EXT_ERROR_MMC_INFORMATION;
130 temp = (unsigned long long)buf.f_bsize*buf.f_bavail;
131 *free_mem = (int)(temp/(1024*1024));
136 int _app2sd_delete_directory(const char *dirname)
140 struct dirent *er = NULL;
141 char abs_filename[FILENAME_MAX] = { 0, };
144 dp = opendir(dirname);
146 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
147 struct stat stFileInfo;
149 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
152 if (lstat(abs_filename, &stFileInfo) < 0) {
153 perror(abs_filename);
158 if (S_ISDIR(stFileInfo.st_mode)) {
159 if (strcmp(ep.d_name, ".")
160 && strcmp(ep.d_name, "..")) {
161 ret = _app2sd_delete_directory(abs_filename);
168 ret = remove(abs_filename);
176 ret = remove(dirname);
180 _E("couldn't open the directory[%s]", dirname);
185 void _app2sd_delete_symlink(const char *dirname)
190 struct dirent *er = NULL;
191 char abs_filename[FILENAME_MAX] = { 0, };
193 _D("start clean_symlink [%s]", dirname);
195 dp = opendir(dirname);
197 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
198 char mmc_path[PATH_MAX] = {0};
200 if (!strcmp(ep.d_name, ".") || !strcmp(ep.d_name, ".."))
203 /*get realpath find symlink to ".mmc" and unlink it*/
204 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep.d_name);
205 char *path = realpath(abs_filename, mmc_path);
207 _E("realpath failed");
210 if (strstr(mmc_path,".mmc")) {
211 _E("force unlink [%s]", abs_filename);
212 if (unlink(abs_filename)) {
213 if (errno == ENOENT) {
214 _E("Unable to access file %s", abs_filename);
216 _E("Unable to delete %s", abs_filename);
224 /*delete ".mmc" folder*/
225 snprintf(abs_filename, FILENAME_MAX, "%s/.mmc", dirname);
226 ret = remove(abs_filename);
231 _E("couldn't open the directory[%s]", dirname);
234 _D("finish clean_symlink");
237 int _app2sd_copy_dir(const char *src, const char *dest)
239 int ret = APP2EXT_SUCCESS;
240 const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
241 ret = _xsystem(argv_bin);
244 return APP2EXT_ERROR_MOVE;
249 int _app2sd_rename_dir(const char *old_name, const char *new_name)
251 int ret = APP2EXT_SUCCESS;
252 const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
253 ret = _xsystem(argv_bin);
255 _E("mv/rename fail");
256 return APP2EXT_ERROR_MOVE;
261 unsigned long long _app2sd_calculate_dir_size(char *dirname)
263 static unsigned long long total = 0;
266 struct dirent *er = NULL;
267 char abs_filename[FILENAME_MAX] = { 0, };;
269 dp = opendir(dirname);
271 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
272 struct stat stFileInfo;
274 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
277 if (stat(abs_filename, &stFileInfo) < 0)
278 perror(abs_filename);
280 total += stFileInfo.st_size;
282 if (S_ISDIR(stFileInfo.st_mode)) {
283 if (strcmp(ep.d_name, ".")
284 && strcmp(ep.d_name, "..")) {
285 _app2sd_calculate_dir_size
295 _E("error in opening directory");
300 unsigned long long _app2sd_calculate_file_size(const char *filename)
302 struct stat stFileInfo;
303 _D("calculating file size for (%s)", filename);
305 if (stat(filename, &stFileInfo) < 0) {
309 return stFileInfo.st_size;
312 /*Note: Don't use any printf statement inside this function*/
313 char *_app2sd_encrypt_device(const char *device,
314 const char *loopback_device, char *passwd)
316 /* TODO : change to dm-crypt */
318 { "/sbin/losetup", device, loopback_device, NULL };
320 int my_pipe[2] = { 0, };
321 char buf[FILENAME_MAX] = { 0, };
322 char *ret_result = NULL;
324 char err_buf[1024] = {0,};
326 if (pipe(my_pipe) < 0) {
327 fprintf(stderr, "Unable to create pipe\n");
333 perror("fork failed");
339 result = dup(my_pipe[1]);
341 strerror_r(errno, err_buf, sizeof(err_buf));
342 fprintf(stderr, "dup failed %d....%s\n",
346 result = dup(my_pipe[1]);
348 strerror_r(errno, err_buf, sizeof(err_buf));
349 fprintf(stderr, "dup failed %d....%s\n",
353 if (execvp(argv[0], (char *const *)argv) < 0) {
354 strerror_r(errno, err_buf, sizeof(err_buf));
355 fprintf(stderr, "execvp failed %d....%s\n",
356 errno, err_buf); /*Don't use d_msg_app2sd */
362 result = read(my_pipe[0], buf, FILENAME_MAX);
364 strerror_r(errno, err_buf, sizeof(err_buf));
365 fprintf(stderr, "read failed %d....%s\n",
371 ret_result = (char *)malloc(strlen(buf) + 1);
372 if (ret_result == NULL) {
376 memset(ret_result, '\0', strlen(buf) + 1);
377 memcpy(ret_result, buf, strlen(buf));
382 /*Note: Don't use any printf statement inside this function*/
383 char *_app2sd_detach_loop_device(const char *device)
385 const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
387 int my_pipe[2] = { 0, };
388 char buf[FILENAME_MAX] = { 0, };
389 char *ret_result = NULL;
391 char err_buf[1024] = {0,};
393 if (pipe(my_pipe) < 0) {
394 fprintf(stderr, "Unable to create pipe\n");
400 perror("fork failed");
406 result = dup(my_pipe[1]);
408 strerror_r(errno, err_buf, sizeof(err_buf));
409 fprintf(stderr, "dup failed %d....%s\n",
413 result = dup(my_pipe[1]);
415 strerror_r(errno, err_buf, sizeof(err_buf));
416 fprintf(stderr, "dup failed %d....%s\n",
420 if (execvp(argv[0], (char *const *)argv) < 0) {
421 fprintf(stderr, "execvp failed\n");
422 /* Don't use d_msg_app2sd */
428 result = read(my_pipe[0], buf, FILENAME_MAX);
430 strerror_r(errno, err_buf, sizeof(err_buf));
431 fprintf(stderr, "read failed %d....%s\n",
437 ret_result = (char *)malloc(strlen(buf) + 1);
438 if (ret_result == NULL) {
442 memset(ret_result, '\0', strlen(buf) + 1);
443 memcpy(ret_result, buf, strlen(buf));
448 /* Note: Don't use any printf statement inside this function*/
449 char *_app2sd_find_associated_device(const char *loopback_device)
451 const char *argv[] = { "/sbin/losetup", "-a", NULL };
453 int my_pipe[2] = { 0, };
454 char buf[FILENAME_MAX] = { 0, };
455 char *ret_result_temp = NULL;
456 char *ret_result = NULL;
458 char *save_str = NULL;
460 char err_buf[1024] = {0,};
462 if (pipe(my_pipe) < 0) {
463 fprintf(stderr, "Unable to create pipe\n");
469 perror("fork failed");
475 result = dup(my_pipe[1]);
477 strerror_r(errno, err_buf, sizeof(err_buf));
478 fprintf(stderr, "dup failed %d....%s\n",
482 result = dup(my_pipe[1]);
484 strerror_r(errno, err_buf, sizeof(err_buf));
485 fprintf(stderr, "dup failed %d....%s\n",
489 if (execvp(argv[0], (char *const *)argv) < 0) {
490 fprintf(stderr, "execvp failed\n");
491 /* Don't use d_msg_app2sd */
497 result = read(my_pipe[0], buf, FILENAME_MAX);
499 strerror_r(errno, err_buf, sizeof(err_buf));
500 fprintf(stderr, "read failed %d....%s\n",
506 ret_result_temp = (char *)malloc(strlen(buf) + 1);
507 if (ret_result_temp == NULL) {
511 memset(ret_result_temp, '\0', strlen(buf) + 1);
512 memcpy(ret_result_temp, buf, strlen(buf));
514 line = strtok_r(ret_result_temp, "\n", &save_str);
516 if (strstr(line, loopback_device) != NULL) {
517 _D("found: (%s)", line);
519 _D("duplicated device");
521 ret_result = strdup(line);
524 line = strtok_r(NULL, "\n", &save_str);
526 free(ret_result_temp);
531 /*Note: Don't use any printf statement inside this function*/
532 char *_app2sd_find_free_device(void)
534 const char *argv[] = { "/sbin/losetup", "-f", NULL };
536 int my_pipe[2] = { 0, };
537 char buf[FILENAME_MAX + 1] = { 0, };
538 char *ret_result = NULL;
540 char err_buf[1024] = {0,};
542 if (pipe(my_pipe) < 0) {
543 fprintf(stderr, "Unable to create pipe\n");
549 perror("fork failed");
555 result = dup(my_pipe[1]);
557 strerror_r(errno, err_buf, sizeof(err_buf));
558 fprintf(stderr, "dup failed %d....%s\n",
562 result = dup(my_pipe[1]);
564 strerror_r(errno, err_buf, sizeof(err_buf));
565 fprintf(stderr, "dup failed %d....%s\n",
569 if (execvp(argv[0], (char *const *)argv) < 0) {
570 fprintf(stderr, "execvp failed\n");
571 /* Don't use d_msg_app2sd */
577 result = read(my_pipe[0], buf, FILENAME_MAX);
579 strerror_r(errno, err_buf, sizeof(err_buf));
580 fprintf(stderr, "read failed %d....%s\n",
586 ret_result = (char *)malloc(strlen(buf) + 1);
587 if (ret_result == NULL) {
591 memset(ret_result, '\0', strlen(buf) + 1);
592 memcpy(ret_result, buf, strlen(buf));
597 /*@_app2sd_generate_password
598 * This is a simple password generator
599 * return: On success, it will return the password, else NULL.
601 char *_app2sd_generate_password(const char *pkgid)
603 char passwd[PASSWD_LEN + 1] = { 0, };
604 char *ret_result = NULL;
605 char set[ASCII_PASSWD_CHAR + 1] =
606 "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
607 "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
608 unsigned char char_1;
609 unsigned char char_2;
611 int appname_len = strlen(pkgid);
615 /* Length of the password */
616 ret_result = (char*)malloc(PASSWD_LEN + 1);
617 if (NULL == ret_result) {
618 _E("unable to allocate memory");
621 memset((void *)ret_result, '\0', PASSWD_LEN + 1);
623 while (i < PASSWD_LEN) {
625 char_1 = (rand_r(&seed) + pkgid[j--]) % ASCII_PASSWD_CHAR;
626 char_2 = rand_r(&seed) % ASCII_PASSWD_CHAR;
627 passwd[i] = set[char_1];
628 passwd[i + 1] = set[(pkgid[j--]) * 2];
629 if (i < PASSWD_LEN - 3)
630 passwd[i + 2] = set[char_2];
634 memcpy(ret_result, passwd, PASSWD_LEN + 1);