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 storage.
110 * param [in]: mmc_path: This is storage 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 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 dp = opendir(dirname);
150 while ((ep = readdir(dp)) != NULL) {
151 char mmc_path[PATH_MAX] = {0};
153 if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
156 /*get realpath find symlink to ".mmc" and unlink it*/
157 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep->d_name);
158 char *path = realpath(abs_filename, mmc_path);
160 _E("realpath failed");
162 if (strstr(mmc_path, ".mmc")) {
163 _E("force unlink [%s]", abs_filename);
164 if (unlink(abs_filename)) {
166 _W("Unable to access file %s", abs_filename);
168 _E("Unable to delete %s", abs_filename);
175 /*delete ".mmc" folder*/
176 snprintf(abs_filename, FILENAME_MAX, "%s/.mmc", dirname);
177 ret = remove(abs_filename);
183 int _app2sd_copy_dir(const char *src, const char *dest)
185 int ret = APP2EXT_SUCCESS;
187 const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
189 /* check existence before copy */
194 if (errno == ENOENT) {
195 _W("src(%s) not exist, skip!", src);
198 _E("failed to open src(%s) dir, errno(%d)", errno);
199 return APP2EXT_ERROR_ACCESS_FILE;
207 if (errno == ENOENT) {
208 _E("dest(%s) not exist, failed!", dest);
209 return APP2EXT_ERROR_ACCESS_FILE;
211 _E("failed to open dest(%s) dir, errno(%d)", errno);
212 return APP2EXT_ERROR_ACCESS_FILE;
216 ret = _xsystem(argv_bin);
218 _E("failed to copy dir, errno(%d)", errno);
219 return APP2EXT_ERROR_ACCESS_FILE;
224 int _app2sd_rename_dir(const char *old_name, const char *new_name)
226 int ret = APP2EXT_SUCCESS;
227 const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
228 ret = _xsystem(argv_bin);
230 _E("mv/rename fail");
231 return APP2EXT_ERROR_ACCESS_FILE;
236 unsigned long long _app2sd_calculate_dir_size(char *dirname)
238 static unsigned long long total = 0;
240 struct dirent *ep = NULL;
241 char abs_filename[FILENAME_MAX] = { 0, };;
243 dp = opendir(dirname);
245 while ((ep = readdir(dp)) != NULL) {
246 struct stat stFileInfo;
248 snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
251 if (stat(abs_filename, &stFileInfo) < 0)
252 perror(abs_filename);
254 total += stFileInfo.st_size;
256 if (S_ISDIR(stFileInfo.st_mode)) {
257 if (strcmp(ep->d_name, ".")
258 && strcmp(ep->d_name, "..")) {
259 _app2sd_calculate_dir_size
269 _E("error in opening directory");
274 unsigned long long _app2sd_calculate_file_size(const char *filename)
276 struct stat stFileInfo;
277 _D("calculating file size for (%s)", filename);
279 if (stat(filename, &stFileInfo) < 0) {
283 return stFileInfo.st_size;
286 /*Note: Don't use any printf statement inside this function*/
287 char *_app2sd_encrypt_device(const char *device,
288 const char *loopback_device, char *passwd)
290 const char *argv[] = { "/sbin/losetup", device,
291 loopback_device, NULL };
293 int my_pipe[2] = { 0, };
294 char buf[FILENAME_MAX] = { 0, };
295 char *ret_result = NULL;
297 char err_buf[1024] = { 0,};
299 if (pipe(my_pipe) < 0) {
300 fprintf(stderr, "Unable to create pipe\n");
306 perror("fork failed");
312 result = dup(my_pipe[1]);
314 strerror_r(errno, err_buf, sizeof(err_buf));
315 fprintf(stderr, "dup failed %d....%s\n",
319 result = dup(my_pipe[1]);
321 strerror_r(errno, err_buf, sizeof(err_buf));
322 fprintf(stderr, "dup failed %d....%s\n",
326 if (execvp(argv[0], (char *const *)argv) < 0) {
327 strerror_r(errno, err_buf, sizeof(err_buf));
328 fprintf(stderr, "execvp failed %d....%s\n",
329 errno, err_buf); /*Don't use d_msg_app2sd */
335 result = read(my_pipe[0], buf, FILENAME_MAX);
337 strerror_r(errno, err_buf, sizeof(err_buf));
338 fprintf(stderr, "read failed %d....%s\n",
344 ret_result = (char *)malloc(strlen(buf) + 1);
345 if (ret_result == NULL) {
349 memset(ret_result, '\0', strlen(buf) + 1);
350 memcpy(ret_result, buf, strlen(buf));
355 /*Note: Don't use any printf statement inside this function*/
356 char *_app2sd_detach_loop_device(const char *device)
358 const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
360 int my_pipe[2] = { 0, };
361 char buf[FILENAME_MAX] = { 0, };
362 char *ret_result = NULL;
364 char err_buf[1024] = {0,};
366 if (pipe(my_pipe) < 0) {
367 fprintf(stderr, "Unable to create pipe\n");
373 perror("fork failed");
379 result = dup(my_pipe[1]);
381 strerror_r(errno, err_buf, sizeof(err_buf));
382 fprintf(stderr, "dup failed %d....%s\n",
386 result = dup(my_pipe[1]);
388 strerror_r(errno, err_buf, sizeof(err_buf));
389 fprintf(stderr, "dup failed %d....%s\n",
393 if (execvp(argv[0], (char *const *)argv) < 0) {
394 fprintf(stderr, "execvp failed\n");
395 /* Don't use d_msg_app2sd */
401 result = read(my_pipe[0], buf, FILENAME_MAX);
403 strerror_r(errno, err_buf, sizeof(err_buf));
404 fprintf(stderr, "read failed %d....%s\n",
410 ret_result = (char *)malloc(strlen(buf) + 1);
411 if (ret_result == NULL) {
415 memset(ret_result, '\0', strlen(buf) + 1);
416 memcpy(ret_result, buf, strlen(buf));
421 /* Note: Don't use any printf statement inside this function*/
422 char *_app2sd_find_associated_device(const char *loopback_device)
424 const char *argv[] = { "/sbin/losetup", "-a", NULL };
426 int my_pipe[2] = { 0, };
427 char buf[FILENAME_MAX] = { 0, };
428 char *ret_result_temp = NULL;
429 char *ret_result = NULL;
431 char *save_str = NULL;
433 char err_buf[1024] = {0,};
435 if (pipe(my_pipe) < 0) {
436 fprintf(stderr, "Unable to create pipe\n");
442 perror("fork failed");
448 result = dup(my_pipe[1]);
450 strerror_r(errno, err_buf, sizeof(err_buf));
451 fprintf(stderr, "dup failed %d....%s\n",
455 result = dup(my_pipe[1]);
457 strerror_r(errno, err_buf, sizeof(err_buf));
458 fprintf(stderr, "dup failed %d....%s\n",
462 if (execvp(argv[0], (char *const *)argv) < 0) {
463 fprintf(stderr, "execvp failed\n");
464 /* Don't use d_msg_app2sd */
470 result = read(my_pipe[0], buf, FILENAME_MAX);
472 strerror_r(errno, err_buf, sizeof(err_buf));
473 fprintf(stderr, "read failed %d....%s\n",
479 ret_result_temp = (char *)malloc(strlen(buf) + 1);
480 if (ret_result_temp == NULL) {
484 memset(ret_result_temp, '\0', strlen(buf) + 1);
485 memcpy(ret_result_temp, buf, strlen(buf));
487 line = strtok_r(ret_result_temp, "\n", &save_str);
489 if (strstr(line, loopback_device) != NULL) {
490 _D("found: (%s)", line);
492 _D("duplicated device");
494 ret_result = strdup(line);
496 line = strtok_r(NULL, "\n", &save_str);
498 free(ret_result_temp);
503 /*Note: Don't use any printf statement inside this function*/
504 char *_app2sd_find_free_device(void)
506 const char *argv[] = { "/sbin/losetup", "-f", NULL };
508 int my_pipe[2] = { 0, };
509 char buf[FILENAME_MAX + 1] = { 0, };
510 char *ret_result = NULL;
512 char err_buf[1024] = {0,};
514 if (pipe(my_pipe) < 0) {
515 fprintf(stderr, "Unable to create pipe\n");
521 perror("fork failed");
527 result = dup(my_pipe[1]);
529 strerror_r(errno, err_buf, sizeof(err_buf));
530 fprintf(stderr, "dup failed %d....%s\n",
534 result = dup(my_pipe[1]);
536 strerror_r(errno, err_buf, sizeof(err_buf));
537 fprintf(stderr, "dup failed %d....%s\n",
541 if (execvp(argv[0], (char *const *)argv) < 0) {
542 fprintf(stderr, "execvp failed\n");
543 /* Don't use d_msg_app2sd */
549 result = read(my_pipe[0], buf, FILENAME_MAX);
551 strerror_r(errno, err_buf, sizeof(err_buf));
552 fprintf(stderr, "read failed %d....%s\n",
558 ret_result = (char *)malloc(strlen(buf) + 1);
559 if (ret_result == NULL) {
563 memset(ret_result, '\0', strlen(buf) + 1);
564 memcpy(ret_result, buf, strlen(buf));
570 * This is a simple password generator
571 * return: On success, it will return the password, else NULL.
573 char *_app2sd_generate_password(void)
576 static const char charset[ASCII_PASSWD_CHAR + 1] =
577 "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
578 "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
581 /* include null byte */
582 passwd = (char *)malloc(sizeof(char) * (PASSWD_LEN + 1));
583 if (passwd == NULL) {
584 _E("unable to allocate memory");
588 for (i = 0; i < PASSWD_LEN; i++)
589 passwd[i] = charset[g_random_int() % ASCII_PASSWD_CHAR];
595 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
596 int _app2sd_check_is_luks_device(const char *device_path)
599 int result = 1; /* default: luks format */
600 const char *argv_bin[] = { "/sbin/cryptsetup", "isLuks", device_path };
601 ret = _xsystem(argv_bin);
603 _E("there was errot to check isLuks");
605 if (ret == 1) /* legacy format */
608 _D("ret(%d), result(%d)", ret, result);