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 <storage-internal.h>
29 #include "app2sd_internals.h"
32 #define ASCII_PASSWD_CHAR 93
35 ########### Internal APIs ##################
38 /* Note: Don't use any printf statement inside this function
39 * This function is similar to Linux's "system()" for executing a process.
41 int _xsystem(const char *argv[])
51 perror("fork failed");
55 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
56 if (execvp(argv[0], (char *const *)argv) < 0)
57 fprintf(stderr, "execvp failed %d....%s\n",
64 if (waitpid(pid, &status, 0) == -1) {
65 perror("waitpid failed");
68 if (WIFSIGNALED(status)) {
72 if (!WIFEXITED(status)) {
73 /* shouldn't happen */
74 perror("should not happen");
77 return WEXITSTATUS(status);
81 * This function checks and returns MMC status
83 int _app2sd_check_mmc_status(char **sdpath)
89 ret = storage_get_primary_sdcard(&storage_id, &sd_mount_path);
90 if (ret != STORAGE_ERROR_NONE) {
91 _E("failed to get primary sdcard (%d)", ret);
92 return APP2EXT_ERROR_MMC_STATUS;
95 _D("primary sdcard: id(%d), mount_path(%s)", storage_id, sd_mount_path);
96 *sdpath = sd_mount_path;
98 return APP2EXT_SUCCESS;
102 * This function returns the available free memory in the storage.
103 * param [in]: mmc_path: This is storage access path.
104 * param [out]: free_mem: Result will be available in this.
105 * User has to pass valid memory address.
106 * return: On success, it will return 0.
107 * Else, appropriate error no will be returned.
109 int _app2sd_get_available_free_memory(char *mmc_path, int *free_mem)
113 unsigned long long temp = 0;
115 if (mmc_path == NULL || free_mem == NULL) {
116 _E("invalid input parameter");
120 memset((void *)&buf, '\0', sizeof(struct statvfs));
122 ret = statvfs(mmc_path, &buf);
124 _E("unable to get memory information");
125 return APP2EXT_ERROR_MMC_INFORMATION;
128 temp = (unsigned long long)buf.f_bsize * buf.f_bavail;
129 *free_mem = (int)(temp/(1024*1024));
134 void _app2sd_delete_symlink(const char *dirname)
139 char abs_filename[FILENAME_MAX];
142 dp = opendir(dirname);
146 while ((ep = readdir(dp)) != NULL) {
147 if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
150 /* get realpath find symlink to ".mmc" and unlink it */
151 snprintf(abs_filename, sizeof(abs_filename), "%s/%s", dirname,
153 mmc_path = realpath(abs_filename, NULL);
155 _E("realpath failed");
159 if (strstr(mmc_path, ".mmc") == NULL) {
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);
175 /* delete ".mmc" directory */
176 snprintf(abs_filename, sizeof(abs_filename), "%s/.mmc", dirname);
177 ret = remove(abs_filename);
179 _W("failed to remove %s", abs_filename);
184 int _app2sd_copy_dir(const char *src, const char *dest)
188 const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
190 /* check existence before copy */
193 if (errno == ENOENT) {
194 _W("src(%s) not exist, skip!", src);
195 return APP2EXT_SUCCESS;
197 _E("failed to open src(%s) dir, errno(%d)", src, errno);
198 return APP2EXT_ERROR_ACCESS_FILE;
205 if (errno == ENOENT) {
206 _E("dest(%s) not exist, failed!", dest);
207 return APP2EXT_ERROR_ACCESS_FILE;
209 _E("failed to open dest(%s) dir: errno(%d)",
211 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)
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;
233 return APP2EXT_SUCCESS;
236 unsigned long long _app2sd_calculate_dir_size(char *dirname)
238 unsigned long long total = 0;
240 struct dirent *ep = NULL;
241 char abs_filename[FILENAME_MAX] = { 0, };;
244 dp = opendir(dirname);
246 _E("error in opening directory");
250 while ((ep = readdir(dp)) != NULL) {
251 snprintf(abs_filename, sizeof(abs_filename), "%s/%s", dirname,
253 if (stat(abs_filename, &sb) < 0) {
254 perror(abs_filename);
258 if (!S_ISDIR(sb.st_mode))
261 if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
263 /* calculate subdirectory */
264 total += _app2sd_calculate_dir_size(abs_filename);
271 unsigned long long _app2sd_calculate_file_size(const char *filename)
274 _D("calculating file size for (%s)", filename);
276 if (stat(filename, &sb) < 0) {
284 /* Note: Don't use any printf statement inside this function */
285 char *_app2sd_execute_command(const char *argv[])
289 char buf[FILENAME_MAX] = { 0, };
295 if (pipe(my_pipe) < 0) {
296 fprintf(stderr, "Unable to create pipe\n");
302 perror("fork failed");
307 result = dup2(my_pipe[1], 1);
309 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
310 fprintf(stderr, "dup failed %d...%s\n", errno, err_str);
313 result = dup2(my_pipe[1], 2);
315 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
316 fprintf(stderr, "dup failed %d...%s\n", errno, err_str);
319 if (execvp(argv[0], (char *const *)argv) < 0) {
320 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
321 fprintf(stderr, "execvp failed %d....%s\n",
328 result = read(my_pipe[0], buf, sizeof(buf) - 1);
330 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
331 fprintf(stderr, "read failed %d..%s\n", errno, err_str);
336 ret_result = strdup(buf);
337 if (ret_result == NULL) {
347 * This is a simple password generator
348 * return: On success, it will return the password, else NULL.
350 char *_app2sd_generate_password(void)
353 static const char charset[ASCII_PASSWD_CHAR + 1] =
354 "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
355 "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
358 /* include null byte */
359 passwd = (char *)malloc(sizeof(char) * (PASSWD_LEN + 1));
360 if (passwd == NULL) {
361 _E("unable to allocate memory");
365 for (i = 0; i < PASSWD_LEN; i++)
366 passwd[i] = charset[g_random_int() % ASCII_PASSWD_CHAR];
372 int _app2sd_check_is_luks_device(const char *device_path)
375 int result = 1; /* default: luks format */
376 const char *argv_bin[] = { "/sbin/cryptsetup", "isLuks", device_path };
377 ret = _xsystem(argv_bin);
379 _E("there was errot to check isLuks");
381 if (ret == 1) /* legacy format */
384 _D("ret(%d), result(%d)", ret, result);
388 int _app2sd_get_loopback_device_path(const char *mmc_path,
389 const char *pkgid, uid_t uid, char *loopback_device, size_t len)
393 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
394 if (encoded_id == NULL)
395 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
397 snprintf(loopback_device, len, "%s/%s/%s", mmc_path, EXTIMG_DIR,
400 return APP2EXT_SUCCESS;