*
*/
+#define _GNU_SOURCE
#include <dirent.h>
-#include <time.h>
+#include <glib.h>
#include <storage-internal.h>
#include "app2sd_internals.h"
########### Internal APIs ##################
*/
-/*Note: Don't use any printf statement inside this function*/
-/*This function is similar to Linux's "system()" for executing a process.*/
+/* Note: Don't use any printf statement inside this function
+ * This function is similar to Linux's "system()" for executing a process.
+ */
int _xsystem(const char *argv[])
{
- int status = 0;
+ int status;
pid_t pid;
- char err_buf[1024] = {0,};
+ char err_buf[1024];
+ const char *err_str;
pid = fork();
switch (pid) {
return -1;
case 0:
/* child */
- strerror_r(errno, err_buf, sizeof(err_buf));
+ err_str = strerror_r(errno, err_buf, sizeof(err_buf));
if (execvp(argv[0], (char *const *)argv) < 0)
fprintf(stderr, "execvp failed %d....%s\n",
- errno, err_buf);
+ errno, err_str);
_exit(-1);
default:
/* parent */
return WEXITSTATUS(status);
}
-
/*
* This function checks and returns MMC status
*/
int _app2sd_check_mmc_status(char **sdpath)
{
- int ret = 0;
- int storage_id = 0;
- char *sd_mount_path = NULL;
+ int ret;
+ int storage_id;
+ char *sd_mount_path;
ret = storage_get_primary_sdcard(&storage_id, &sd_mount_path);
if (ret != STORAGE_ERROR_NONE) {
_E("failed to get primary sdcard (%d)", ret);
- if (sd_mount_path)
- free(sd_mount_path);
return APP2EXT_ERROR_MMC_STATUS;
}
- if (sd_mount_path) {
- _D("primary sdcard: id(%d), mount_path(%s)",
- storage_id, sd_mount_path);
- *sdpath = sd_mount_path;
- return APP2EXT_SUCCESS;
- }
- _E("there is no primary sdcard");
- if (sd_mount_path)
- free(sd_mount_path);
+ _D("primary sdcard: id(%d), mount_path(%s)", storage_id, sd_mount_path);
+ *sdpath = sd_mount_path;
- return APP2EXT_ERROR_MMC_STATUS;
+ return APP2EXT_SUCCESS;
}
/*
- * This function returns the available free memory in the SD Card.
- * param [in]: sd_path: This is sd card access path.
+ * This function returns the available free memory in the storage.
+ * param [in]: mmc_path: This is storage access path.
* param [out]: free_mem: Result will be available in this.
* User has to pass valid memory address.
* return: On success, it will return 0.
ret = statvfs(mmc_path, &buf);
if (ret) {
- _E("unable to get SD Card memory information");
+ _E("unable to get memory information");
return APP2EXT_ERROR_MMC_INFORMATION;
}
- temp = (unsigned long long)buf.f_bsize*buf.f_bavail;
+ temp = (unsigned long long)buf.f_bsize * buf.f_bavail;
*free_mem = (int)(temp/(1024*1024));
return 0;
void _app2sd_delete_symlink(const char *dirname)
{
- int ret = 0;
- DIR *dp = NULL;
- struct dirent ep;
- struct dirent *er = NULL;
- char abs_filename[FILENAME_MAX] = { 0, };
-
- _D("start clean_symlink [%s]", dirname);
+ int ret;
+ DIR *dp;
+ struct dirent *ep;
+ char abs_filename[FILENAME_MAX];
+ char *mmc_path;
dp = opendir(dirname);
- if (dp != NULL) {
- while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
- char mmc_path[PATH_MAX] = {0};
-
- if (!strcmp(ep.d_name, ".") || !strcmp(ep.d_name, ".."))
- continue;
-
- /*get realpath find symlink to ".mmc" and unlink it*/
- snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep.d_name);
- char *path = realpath(abs_filename, mmc_path);
- if (!path)
- _E("realpath failed");
-
- if (strstr(mmc_path, ".mmc")) {
- _E("force unlink [%s]", abs_filename);
- if (unlink(abs_filename)) {
- if (errno == ENOENT)
- _W("Unable to access file %s", abs_filename);
- else
- _E("Unable to delete %s", abs_filename);
- }
- }
+ if (dp == NULL)
+ return;
+
+ while ((ep = readdir(dp)) != NULL) {
+ if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
+ continue;
+
+ /* get realpath find symlink to ".mmc" and unlink it */
+ snprintf(abs_filename, sizeof(abs_filename), "%s/%s", dirname,
+ ep->d_name);
+ mmc_path = realpath(abs_filename, NULL);
+ if (!mmc_path) {
+ _E("realpath failed");
+ continue;
+ }
+ if (strstr(mmc_path, ".mmc") == NULL) {
+ free(mmc_path);
+ continue;
}
- (void)closedir(dp);
-
- /*delete ".mmc" folder*/
- snprintf(abs_filename, FILENAME_MAX, "%s/.mmc", dirname);
- ret = remove(abs_filename);
- if (ret == -1)
- return;
- } else {
- _E("couldn't open the directory[%s]", dirname);
- }
+ free(mmc_path);
- _D("finish clean_symlink");
+ _E("force unlink [%s]", abs_filename);
+ if (unlink(abs_filename)) {
+ if (errno == ENOENT)
+ _W("Unable to access file %s", abs_filename);
+ else
+ _E("Unable to delete %s", abs_filename);
+ }
+ }
+ (void)closedir(dp);
+
+ /* delete ".mmc" directory */
+ snprintf(abs_filename, sizeof(abs_filename), "%s/.mmc", dirname);
+ ret = remove(abs_filename);
+ if (ret == -1) {
+ _W("failed to remove %s", abs_filename);
+ return;
+ }
}
int _app2sd_copy_dir(const char *src, const char *dest)
{
- int ret = APP2EXT_SUCCESS;
- DIR *dir = NULL;
+ int ret;
+ DIR *dir;
const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
/* check existence before copy */
dir = opendir(src);
- if (dir) {
- closedir(dir);
- } else {
+ if (dir == NULL) {
if (errno == ENOENT) {
_W("src(%s) not exist, skip!", src);
- return ret;
+ return APP2EXT_SUCCESS;
} else {
- _E("failed to open src(%s) dir, errno(%d)", errno);
- return APP2EXT_ERROR_MOVE;
+ _E("failed to open src(%s) dir, errno(%d)", src, errno);
+ return APP2EXT_ERROR_ACCESS_FILE;
}
}
+ closedir(dir);
dir = opendir(dest);
- if (dir) {
- closedir(dir);
- } else {
+ if (dir == NULL) {
if (errno == ENOENT) {
_E("dest(%s) not exist, failed!", dest);
- return APP2EXT_ERROR_MOVE;
+ return APP2EXT_ERROR_ACCESS_FILE;
} else {
- _E("failed to open dest(%s) dir, errno(%d)", errno);
- return APP2EXT_ERROR_MOVE;
+ _E("failed to open dest(%s) dir: errno(%d)",
+ dest, errno);
+ return APP2EXT_ERROR_ACCESS_FILE;
}
}
+ closedir(dir);
ret = _xsystem(argv_bin);
if (ret) {
_E("failed to copy dir, errno(%d)", errno);
- return APP2EXT_ERROR_MOVE;
+ return APP2EXT_ERROR_ACCESS_FILE;
}
return ret;
}
int _app2sd_rename_dir(const char *old_name, const char *new_name)
{
- int ret = APP2EXT_SUCCESS;
+ int ret;
const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
ret = _xsystem(argv_bin);
if (ret) {
_E("mv/rename fail");
- return APP2EXT_ERROR_MOVE;
+ return APP2EXT_ERROR_ACCESS_FILE;
}
- return ret;
+ return APP2EXT_SUCCESS;
}
unsigned long long _app2sd_calculate_dir_size(char *dirname)
{
- static unsigned long long total = 0;
+ unsigned long long total = 0;
DIR *dp = NULL;
- struct dirent ep;
- struct dirent *er = NULL;
+ struct dirent *ep = NULL;
char abs_filename[FILENAME_MAX] = { 0, };;
+ struct stat sb;
dp = opendir(dirname);
- if (dp != NULL) {
- while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
- struct stat stFileInfo;
-
- snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
- ep.d_name);
-
- if (stat(abs_filename, &stFileInfo) < 0)
- perror(abs_filename);
- else {
- total += stFileInfo.st_size;
-
- if (S_ISDIR(stFileInfo.st_mode)) {
- if (strcmp(ep.d_name, ".")
- && strcmp(ep.d_name, "..")) {
- _app2sd_calculate_dir_size
- (abs_filename);
- }
- } else {
- /*Do Nothing */
- }
- }
- }
- (void)closedir(dp);
- } else {
+ if (dp == NULL) {
_E("error in opening directory");
+ return 0;
+ }
+
+ while ((ep = readdir(dp)) != NULL) {
+ snprintf(abs_filename, sizeof(abs_filename), "%s/%s", dirname,
+ ep->d_name);
+ if (stat(abs_filename, &sb) < 0) {
+ perror(abs_filename);
+ continue;
+ }
+ total += sb.st_size;
+ if (!S_ISDIR(sb.st_mode))
+ continue;
+
+ if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
+ continue;
+ /* calculate subdirectory */
+ total += _app2sd_calculate_dir_size(abs_filename);
}
+ (void)closedir(dp);
+
return total;
}
unsigned long long _app2sd_calculate_file_size(const char *filename)
{
- struct stat stFileInfo;
+ struct stat sb;
_D("calculating file size for (%s)", filename);
- if (stat(filename, &stFileInfo) < 0) {
+ if (stat(filename, &sb) < 0) {
perror(filename);
return 0;
- } else
- return stFileInfo.st_size;
+ }
+
+ return sb.st_size;
}
-/*Note: Don't use any printf statement inside this function*/
-char *_app2sd_encrypt_device(const char *device,
- const char *loopback_device, char *passwd)
+/* Note: Don't use any printf statement inside this function */
+char *_app2sd_execute_command(const char *argv[])
{
- const char *argv[] = { "/sbin/losetup", device,
- loopback_device, NULL };
- pid_t pid = 0;
- int my_pipe[2] = { 0, };
+ pid_t pid;
+ int my_pipe[2];
char buf[FILENAME_MAX] = { 0, };
- char *ret_result = NULL;
- int result = 0;
- char err_buf[1024] = { 0,};
+ char *ret_result;
+ int result;
+ char err_buf[1024];
+ const char *err_str;
if (pipe(my_pipe) < 0) {
fprintf(stderr, "Unable to create pipe\n");
return NULL;
case 0:
/* child */
- close(1);
- close(2);
- result = dup(my_pipe[1]);
+ close(0);
+ result = dup2(my_pipe[1], 1);
if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "dup failed %d....%s\n",
- errno, err_buf);
+ err_str = strerror_r(errno, err_buf, sizeof(err_buf));
+ fprintf(stderr, "dup failed %d...%s\n", errno, err_str);
_exit(-1);
}
- result = dup(my_pipe[1]);
+ result = dup2(my_pipe[1], 2);
if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "dup failed %d....%s\n",
- errno, err_buf);
+ err_str = strerror_r(errno, err_buf, sizeof(err_buf));
+ fprintf(stderr, "dup failed %d...%s\n", errno, err_str);
_exit(-1);
}
if (execvp(argv[0], (char *const *)argv) < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
+ err_str = strerror_r(errno, err_buf, sizeof(err_buf));
fprintf(stderr, "execvp failed %d....%s\n",
- errno, err_buf); /*Don't use d_msg_app2sd */
+ errno, err_str);
}
_exit(-1);
default:
/* parent */
close(my_pipe[1]);
- result = read(my_pipe[0], buf, FILENAME_MAX);
+ result = read(my_pipe[0], buf, sizeof(buf) - 1);
if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "read failed %d....%s\n",
- errno, err_buf);
+ err_str = strerror_r(errno, err_buf, sizeof(err_buf));
+ fprintf(stderr, "read failed %d..%s\n", errno, err_str);
}
break;
}
- ret_result = (char *)malloc(strlen(buf) + 1);
+ ret_result = strdup(buf);
if (ret_result == NULL) {
- _E("malloc failed");
+ _E("strdup failed");
return NULL;
}
- memset(ret_result, '\0', strlen(buf) + 1);
- memcpy(ret_result, buf, strlen(buf));
return ret_result;
+
}
-/*Note: Don't use any printf statement inside this function*/
-char *_app2sd_detach_loop_device(const char *device)
-{
- const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
- pid_t pid;
- int my_pipe[2] = { 0, };
- char buf[FILENAME_MAX] = { 0, };
- char *ret_result = NULL;
- int result = 0;
- char err_buf[1024] = {0,};
+static int generate_random_num(unsigned short* buf, int len) {
+ int fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0)
+ return -1;
- if (pipe(my_pipe) < 0) {
- fprintf(stderr, "Unable to create pipe\n");
- return NULL;
- }
- pid = fork();
- switch (pid) {
- case -1:
- perror("fork failed");
- return NULL;
- case 0:
- /* child */
- close(1);
- close(2);
- result = dup(my_pipe[1]);
- if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "dup failed %d....%s\n",
- errno, err_buf);
- _exit(-1);
- }
- result = dup(my_pipe[1]);
- if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "dup failed %d....%s\n",
- errno, err_buf);
- _exit(-1);
- }
- if (execvp(argv[0], (char *const *)argv) < 0) {
- fprintf(stderr, "execvp failed\n");
- /* Don't use d_msg_app2sd */
- }
- _exit(-1);
- default:
- /* parent */
- close(my_pipe[1]);
- result = read(my_pipe[0], buf, FILENAME_MAX);
- if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "read failed %d....%s\n",
- errno, err_buf);
- }
- break;
- }
+ if (read(fd, buf, len) < 0) {
+ close(fd);
+ return -1;
+ }
- ret_result = (char *)malloc(strlen(buf) + 1);
- if (ret_result == NULL) {
- _E("malloc failed");
- return NULL;
- }
- memset(ret_result, '\0', strlen(buf) + 1);
- memcpy(ret_result, buf, strlen(buf));
+ close(fd);
- return ret_result;
+ return 0;
}
-/* Note: Don't use any printf statement inside this function*/
-char *_app2sd_find_associated_device(const char *loopback_device)
+/*
+* This is a simple password generator
+* return: On success, it will return the password, else NULL.
+*/
+char *_app2sd_generate_password(void)
{
- const char *argv[] = { "/sbin/losetup", "-a", NULL };
- pid_t pid;
- int my_pipe[2] = { 0, };
- char buf[FILENAME_MAX] = { 0, };
- char *ret_result_temp = NULL;
- char *ret_result = NULL;
- char *line = NULL;;
- char *save_str = NULL;
- int result = 0;
- char err_buf[1024] = {0,};
+ char *passwd;
+ static const char charset[ASCII_PASSWD_CHAR + 1] =
+ "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
+ "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
+ int i;
+ unsigned short rand_nums[PASSWD_LEN];
- if (pipe(my_pipe) < 0) {
- fprintf(stderr, "Unable to create pipe\n");
+ if (generate_random_num(rand_nums, sizeof(rand_nums)) < 0) {
+ _E("Failed to read random data");
return NULL;
}
- pid = fork();
- switch (pid) {
- case -1:
- perror("fork failed");
- return NULL;
- case 0:
- /* child */
- close(1);
- close(2);
- result = dup(my_pipe[1]);
- if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "dup failed %d....%s\n",
- errno, err_buf);
- _exit(-1);
- }
- result = dup(my_pipe[1]);
- if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "dup failed %d....%s\n",
- errno, err_buf);
- _exit(-1);
- }
- if (execvp(argv[0], (char *const *)argv) < 0) {
- fprintf(stderr, "execvp failed\n");
- /* Don't use d_msg_app2sd */
- }
- _exit(-1);
- default:
- /* parent */
- close(my_pipe[1]);
- result = read(my_pipe[0], buf, FILENAME_MAX);
- if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "read failed %d....%s\n",
- errno, err_buf);
- }
- break;
- }
- ret_result_temp = (char *)malloc(strlen(buf) + 1);
- if (ret_result_temp == NULL) {
- _E("malloc failed");
+ /* include null byte */
+ passwd = (char *)malloc(sizeof(char) * (PASSWD_LEN + 1));
+ if (passwd == NULL) {
+ _E("unable to allocate memory");
return NULL;
}
- memset(ret_result_temp, '\0', strlen(buf) + 1);
- memcpy(ret_result_temp, buf, strlen(buf));
-
- line = strtok_r(ret_result_temp, "\n", &save_str);
- while (line) {
- if (strstr(line, loopback_device) != NULL) {
- _D("found: (%s)", line);
- if (ret_result)
- _D("duplicated device");
- else
- ret_result = strdup(line);
- }
- line = strtok_r(NULL, "\n", &save_str);
- }
- free(ret_result_temp);
- return ret_result;
+ for (i = 0; i < PASSWD_LEN; i++)
+ passwd[i] = charset[rand_nums[i] % ASCII_PASSWD_CHAR];
+ passwd[i] = '\0';
+
+ return passwd;
}
-/*Note: Don't use any printf statement inside this function*/
-char *_app2sd_find_free_device(void)
+int _app2sd_check_is_luks_device(const char *device_path)
{
- const char *argv[] = { "/sbin/losetup", "-f", NULL };
- pid_t pid;
- int my_pipe[2] = { 0, };
- char buf[FILENAME_MAX + 1] = { 0, };
- char *ret_result = NULL;
- int result = 0;
- char err_buf[1024] = {0,};
-
- if (pipe(my_pipe) < 0) {
- fprintf(stderr, "Unable to create pipe\n");
- return NULL;
- }
- pid = fork();
- switch (pid) {
- case -1:
- perror("fork failed");
- return NULL;
- case 0:
- /* child */
- close(1);
- close(2);
- result = dup(my_pipe[1]);
- if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "dup failed %d....%s\n",
- errno, err_buf);
- _exit(-1);
- }
- result = dup(my_pipe[1]);
- if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "dup failed %d....%s\n",
- errno, err_buf);
- _exit(-1);
- }
- if (execvp(argv[0], (char *const *)argv) < 0) {
- fprintf(stderr, "execvp failed\n");
- /* Don't use d_msg_app2sd */
- }
- _exit(-1);
- default:
- /* parent */
- close(my_pipe[1]);
- result = read(my_pipe[0], buf, FILENAME_MAX);
- if (result < 0) {
- strerror_r(errno, err_buf, sizeof(err_buf));
- fprintf(stderr, "read failed %d....%s\n",
- errno, err_buf);
- }
- break;
- }
+ int ret = 0;
+ int result = 1; /* default: luks format */
+ const char *argv_bin[] = { "/sbin/cryptsetup", "isLuks", device_path };
+ ret = _xsystem(argv_bin);
+ if (ret < 0)
+ _E("there was errot to check isLuks");
- ret_result = (char *)malloc(strlen(buf) + 1);
- if (ret_result == NULL) {
- _E("malloc failed");
- return NULL;
- }
- memset(ret_result, '\0', strlen(buf) + 1);
- memcpy(ret_result, buf, strlen(buf));
+ if (ret == 1) /* legacy format */
+ result = 0;
- return ret_result;
+ _D("ret(%d), result(%d)", ret, result);
+ return result;
}
-/*
-* This is a simple password generator
-* return: On success, it will return the password, else NULL.
-*/
-char *_app2sd_generate_password(const char *pkgid)
+int _app2sd_get_loopback_device_path(const char *mmc_path,
+ const char *pkgid, uid_t uid, char *loopback_device, size_t len)
{
- char passwd[PASSWD_LEN + 1] = { 0, };
- char *ret_result = NULL;
- char set[ASCII_PASSWD_CHAR + 1] =
- "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
- "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
- unsigned char char_1;
- unsigned char char_2;
- int i = 0;
- int appname_len = strlen(pkgid);
- int j = appname_len;
- unsigned int seed;
-
- /* length of the password */
- ret_result = (char *)malloc(PASSWD_LEN + 1);
- if (NULL == ret_result) {
- _E("unable to allocate memory");
- return NULL;
- }
- memset((void *)ret_result, '\0', PASSWD_LEN + 1);
-
- while (i < PASSWD_LEN) {
- seed = time(NULL);
- if (j > 0) j--;
- char_1 = (rand_r(&seed) + pkgid[j]) % ASCII_PASSWD_CHAR;
- char_2 = rand_r(&seed) % ASCII_PASSWD_CHAR;
- passwd[i] = set[char_1];
- if (j > 0) j--;
- passwd[i + 1] = set[((pkgid[j]) * 2) % ASCII_PASSWD_CHAR];
- if (i < PASSWD_LEN - 3)
- passwd[i + 2] = set[char_2];
- i++;
- }
+ char *encoded_id;
- memcpy(ret_result, passwd, PASSWD_LEN + 1);
+ encoded_id = _app2sd_get_encoded_name(pkgid, uid);
+ if (encoded_id == NULL)
+ return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
- return ret_result;
+ snprintf(loopback_device, len, "%s/%s/%s", mmc_path, EXTIMG_DIR,
+ encoded_id);
+ free(encoded_id);
+ return APP2EXT_SUCCESS;
}