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.
25 #include <openssl/sha.h>
29 #include "app2sd_internals.h"
31 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
32 #define DMCRYPT_ITER_TIME 50
33 #define DMCRYPT_KEY_LEN 128
36 static int _app2sd_make_directory(const char *path, uid_t uid)
40 mode_t mode = DIR_PERMS;
42 struct passwd *pwd_result;
43 char buf[1024] = { 0, };
45 ret = _app2sd_delete_directory(path);
47 _E("unable to delete (%s)", path);
48 return APP2EXT_ERROR_DELETE_DIRECTORY;
51 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
52 if (ret != 0 || pwd_result == NULL) {
53 _E("get uid failed(%d)", ret);
54 return APP2EXT_ERROR_ACCESS_FILE;
56 _D("uid(%d), gid(%d)", uid, pwd.pw_gid);
58 /* create directory */
59 ret = mkdir(path, mode);
61 if (errno != EEXIST) {
62 _E("create directory failed," \
63 " error no is (%d)", errno);
64 return APP2EXT_ERROR_CREATE_DIRECTORY;
68 fd = open(path, O_RDONLY|O_DIRECTORY);
70 _E("can't open path(%s)", path);
71 return APP2EXT_ERROR_OPEN_DIR;
74 ret = fchmod(fd, 0755);
76 _E("change file permission error");
78 return APP2EXT_ERROR_ACCESS_FILE;
81 ret = fchown(fd, uid, pwd.pw_gid);
83 _E("change file owner error");
85 return APP2EXT_ERROR_ACCESS_FILE;
90 return APP2EXT_SUCCESS;
93 char *_app2sd_find_associated_device_node(const char *loopback_device)
95 char *ret_result = NULL;
98 char dev[FILENAME_MAX] = { 0, };
101 result = (char *)_app2sd_find_associated_device(loopback_device);
102 if (result == NULL) {
103 _D("there is no the associated file (%s)", loopback_device);
107 /* process the string*/
108 snprintf(dev, FILENAME_MAX - 1, "%s", result);
110 if (strstr(dev, "dev") == NULL) {
111 _E("unable to find the associated file");
115 char *saveptr = NULL;
116 ret_result = strtok_r(dev, delims, &saveptr);
118 devnode = strdup(ret_result);
126 char *_app2sd_create_loopdevice_node(void)
128 char *ret_result = NULL;
129 mode_t mode = DIR_PERMS;
131 int ret = APP2EXT_SUCCESS;
135 result = (char *)_app2sd_find_free_device();
136 _D("find_free_device(%s)", result);
138 /* validate the result */
139 if (result == NULL || strstr(result, "/dev") == NULL) {
140 _D("no device found, creating device node");
147 char dev_path[BUF_SIZE] = { 0, };
148 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
149 while ((fp = fopen(dev_path, "r+")) != NULL) {
151 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
152 _D("next dev path for checking is (%s)",
156 _D("device node candidate is (%s)", dev_path);
158 dev_node = makedev(DEV_MAJOR, count);
159 ret = mknod(dev_path, S_IFBLK | mode, dev_node);
161 _E("error while creating the device node: errno is (%d)",
165 ret_result = (char *)malloc(strlen(dev_path) + 1);
166 if (ret_result == NULL) {
167 _E("unable to allocate memory");
170 memset(ret_result, '\0', strlen(dev_path) + 1);
171 memcpy(ret_result, dev_path, strlen(dev_path));
173 ret_result = (char *)malloc(strlen(result) + 1);
174 if (ret_result == NULL) {
180 memset(ret_result, '\0', strlen(result) + 1);
181 if (strlen(result) > 0)
182 memcpy(ret_result, result, strlen(result) - 1);
191 char *_app2sd_do_loopback_encryption_setup(const char *pkgid,
192 const char *loopback_device, uid_t uid)
194 int ret = APP2EXT_SUCCESS;
197 char *device_node = NULL;
200 _E("invalid argument");
204 /* get password for loopback encryption */
205 ret = _app2sd_initialize_db();
207 _E("app2sd db initialize failed");
211 if ((passwd = _app2sd_get_password_from_db(pkgid, uid)) == NULL) {
212 passwd = (char *)_app2sd_generate_password(pkgid);
213 if (NULL == passwd) {
214 _E("unable to generate password");
217 if ((ret = _app2sd_set_info_in_db(pkgid,
218 passwd, loopback_device, uid)) < 0) {
219 _E("unable to save info");
227 /* get free device node*/
228 device_node = _app2sd_create_loopdevice_node();
229 if (NULL == device_node) {
232 _E("unable to find free loopback node");
236 _D("device_node (%s)", device_node);
238 result = (char *)_app2sd_encrypt_device(device_node,
239 loopback_device, passwd);
240 if (result == NULL) {
241 _E("encryption failed");
246 _D("result (%s)", result);
255 char *_app2sd_do_loopback_duplicate_encryption_setup(const char *pkgid,
256 const char *temp_pkgid, const char *temp_loopback_device,
257 char *passwd, uid_t uid)
260 char *device_node = NULL;
262 if (pkgid == NULL || temp_pkgid == NULL ||
263 temp_loopback_device == NULL || passwd == NULL) {
264 _E("invalid argument");
268 /* get free device node*/
269 device_node = _app2sd_create_loopdevice_node();
270 if (NULL == device_node) {
271 _E("unable to find free loopback node");
274 result = (char *)_app2sd_encrypt_device(device_node,
275 temp_loopback_device, passwd);
276 if (result == NULL) {
277 _E("encryption failed");
280 if (strlen(result) == 0) {
285 _E("error is (%s)", result);
295 int _app2sd_remove_loopback_encryption_setup(const char *loopback_device)
297 int ret = APP2EXT_SUCCESS;
299 char *dev_node = NULL;
301 if ((dev_node = _app2sd_find_associated_device_node(loopback_device))
303 _E("Unable to find the association");
304 ret = APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE;
307 result = (char *)_app2sd_detach_loop_device(dev_node);
308 if (result == NULL) {
309 _E("error in detaching");
310 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
324 int _app2sd_remove_all_loopback_encryption_setups(const char *loopback_device)
326 int ret = APP2EXT_SUCCESS;
328 char *dev_node = NULL;
331 _app2sd_find_associated_device_node(loopback_device))
333 _E("finish to find the association");
334 ret = APP2EXT_SUCCESS;
338 _D("find node (%s)", dev_node);
340 result = (char *)_app2sd_detach_loop_device(dev_node);
341 if (result == NULL) {
342 _E("error in detaching");
343 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
358 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
359 int _app2sd_dmcrypt_setup_device(const char *pkgid,
360 const char *loopback_device, bool is_dup, uid_t uid)
362 int ret = APP2EXT_SUCCESS;
364 char dmcrypt_setup_cmd[BUF_SIZE] = { 0, };
365 char err_buf[BUF_SIZE] = { 0, };
367 if (pkgid == NULL || loopback_device == NULL) {
368 _E("invalid argument");
369 return APP2EXT_ERROR_INVALID_ARGUMENTS;
372 /* get password for dmcrypt encryption */
373 ret = _app2sd_initialize_db();
375 _E("app2sd db initialize failed");
376 return APP2EXT_ERROR_DB_INITIALIZE;
379 passwd = _app2sd_get_password_from_db(pkgid, uid);
380 if (passwd == NULL) {
382 _E("no password found for (%s)", pkgid);
383 return APP2EXT_ERROR_SQLITE_REGISTRY;
385 passwd = (char *)_app2sd_generate_password(pkgid);
386 if (NULL == passwd) {
387 _E("unable to generate password\n");
388 return APP2EXT_ERROR_PASSWD_GENERATION;
390 if ((ret = _app2sd_set_info_in_db(pkgid, passwd,
391 loopback_device, uid)) < 0) {
392 _E("unable to save password");
395 return APP2EXT_ERROR_SQLITE_REGISTRY;
400 snprintf(dmcrypt_setup_cmd, BUF_SIZE, "/bin/echo '%s' | /sbin/cryptsetup -q -i %d " \
401 "-c aes-cbc-lmk -s %d --align-payload=8 luksFormat %s",
402 passwd, DMCRYPT_ITER_TIME, DMCRYPT_KEY_LEN, loopback_device);
404 ret = system(dmcrypt_setup_cmd);
406 strerror_r(errno, err_buf, sizeof(err_buf));
407 _E("Error setting up dmcrypt on app2sd file, " \
408 "error(%s), ret(%d)", err_buf, ret);
413 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
424 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
425 bool is_dup, uid_t uid, char **dev_node)
427 int ret = APP2EXT_SUCCESS;
429 char dmcrypt_open_cmd[BUF_SIZE] = { 0, };
430 char dev_name[BUF_SIZE] = { 0, };
431 char buf[BUF_SIZE] = { 0, };
434 if (pkgid == NULL || loopback_device == NULL) {
435 _E("invalid argument");
436 return APP2EXT_ERROR_INVALID_ARGUMENTS;
440 snprintf(dev_name, BUF_SIZE, "%s.new_%d", pkgid, uid);
442 snprintf(dev_name, BUF_SIZE, "%s_%d", pkgid, uid);
444 /* get password for dmcrypt encryption */
445 ret = _app2sd_initialize_db();
447 _E("app2sd db initialize failed");
448 return APP2EXT_ERROR_DB_INITIALIZE;
450 if ((passwd = _app2sd_get_password_from_db(pkgid, uid)) == NULL) {
451 _E("no password found for [%s]", pkgid);
452 return APP2EXT_ERROR_SQLITE_REGISTRY;
455 snprintf(dmcrypt_open_cmd, BUF_SIZE, "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen %s %s",
456 passwd, loopback_device, dev_name);
458 ret = system(dmcrypt_open_cmd);
460 strerror_r(errno, buf, sizeof(buf));
461 _E("error opening dmcrypt device, error: [%s]", buf);
462 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
465 snprintf(buf, BUF_SIZE, "/dev/mapper/%s", dev_name);
467 *dev_node = (char *)calloc(len + 1, sizeof(char));
468 if (*dev_node == NULL) {
469 _E("memory alloc failed");
470 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
472 snprintf(*dev_node, len + 1, "%s", buf);
477 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
479 int ret = APP2EXT_SUCCESS;
480 char dev_node[BUF_SIZE] = { '\0' };
481 char dmcrypt_close_cmd[BUF_SIZE] = { '\0' };
482 char err_buf[BUF_SIZE] = { '\0' };
483 char *t_dev_node = NULL;
486 _E("invalid argument\n");
487 return APP2EXT_ERROR_INVALID_ARGUMENTS;
490 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
492 _E("no associated device node(%s_%d) found", pkgid, uid);
493 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
499 snprintf(dev_node, BUF_SIZE, "/dev/mapper/%s_%d", pkgid, uid);
500 snprintf(dmcrypt_close_cmd, BUF_SIZE, "/sbin/cryptsetup -q luksClose %s", dev_node);
501 ret = system(dmcrypt_close_cmd);
503 strerror_r(errno, err_buf, sizeof(err_buf));
504 _E("error closing dmcrypt on app2sd file,"\
505 " error: [%s]", err_buf);
506 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
512 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
514 char *dev_node = NULL;
515 char buf[BUF_SIZE] = { 0, };
518 snprintf(buf, BUF_SIZE, "/dev/mapper/%s_%d", pkgid, uid);
520 dev_node = (char *)calloc(len + 1, sizeof(char));
521 if (dev_node == NULL) {
522 _E("memory alloc failed");
525 snprintf(dev_node, len + 1, "%s", buf);
527 if (access(dev_node, F_OK) == 0) {
528 _D("device_node: (%s)", dev_node);
538 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
539 const char *temp_loopback_device, uid_t uid)
541 int ret = APP2EXT_SUCCESS;
542 char *device_node = NULL;
544 if (pkgid == NULL || temp_loopback_device == NULL) {
545 _E("invalid argument\n");
549 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true, uid);
551 _E("dmcrypt setup device error(%d)", ret);
555 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
558 _E("dmcrypt open device error");
566 int _app2sd_create_loopback_device(const char *pkgid,
567 const char *loopback_device, int size)
569 int ret = APP2EXT_SUCCESS;
570 char command[FILENAME_MAX] = { 0, };
571 char buff[BUF_SIZE] = { 0, };
574 if (NULL == pkgid || size <= 0) {
575 _E("invalid argument");
576 return APP2EXT_ERROR_INVALID_ARGUMENTS;
578 snprintf(command, FILENAME_MAX - 1, "of=%s", loopback_device);
579 snprintf(buff, BUF_SIZE - 1, "count=%d", size);
581 const char *argv1[] = { "/bin/dd", "if=/dev/zero",
582 command, "bs=1M", buff, NULL };
584 if ((fp = fopen(loopback_device, "r+")) != NULL) {
585 _W("encrypted file already exists (%s)",
588 return APP2EXT_ERROR_PKG_EXISTS;
591 ret = _xsystem(argv1);
593 _E("command (%s) failed, ret(%d), errno(%d)", command, ret, errno);
598 int _app2sd_delete_loopback_device(const char *loopback_device)
600 int ret = APP2EXT_SUCCESS;
602 ret = unlink(loopback_device);
604 if (errno == ENOENT) {
605 _W("unable to access file (%s)", loopback_device);
607 _E("unable to delete (%s)", loopback_device);
608 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
612 return APP2EXT_SUCCESS;
615 int _app2sd_create_file_system(const char *device_path)
617 int ret = APP2EXT_SUCCESS;
619 char err_buf[1024] = {0,};
621 if (device_path == NULL) {
623 return APP2EXT_ERROR_INVALID_ARGUMENTS;
626 /* Format the filesystem [create a filesystem]*/
627 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
628 fp = fopen(device_path, "r+");
630 strerror_r(errno, err_buf, sizeof(err_buf));
631 _E("unable to access (%s) error is (%d, %s)",
632 device_path, errno, err_buf);
633 return APP2EXT_ERROR_ACCESS_FILE;
637 ret = _xsystem(argv);
639 strerror_r(errno, err_buf, sizeof(err_buf));
640 _E("creating file system failed, error is (%s)",
642 return APP2EXT_ERROR_CREATE_FS;
647 static int _app2sd_create_dir_with_link(const char *application_path,
648 const char *pkgid, const char *dir_name, uid_t uid)
650 int ret = APP2EXT_SUCCESS;
651 char application_dir_mmc_path[FILENAME_MAX] = { 0, };
652 char application_dir_path[FILENAME_MAX] = { 0, };
654 snprintf(application_dir_mmc_path, FILENAME_MAX - 1, "%s/.mmc/%s",
655 application_path, dir_name);
656 snprintf(application_dir_path, FILENAME_MAX, "%s/%s",
657 application_path, dir_name);
659 ret = _app2sd_make_directory(application_dir_mmc_path, uid);
661 _E("create directory failed");
662 return APP2EXT_ERROR_CREATE_DIRECTORY;
665 if ((ret = symlink(application_dir_mmc_path,
666 application_dir_path)) < 0) {
667 if (errno == EEXIST) {
668 _D("file with symlink name present (%s)",
669 application_dir_path);
671 _E("symbolic link creation "
672 "failed, error no is (%d)", errno);
673 return APP2EXT_ERROR_CREATE_SYMLINK;
677 return APP2EXT_SUCCESS;
680 static int _app2sd_create_directory_entry(const char *application_path,
681 const char *pkgid, GList *dir_list, uid_t uid)
683 int ret = APP2EXT_SUCCESS;
685 app2ext_dir_details *dir_detail = NULL;
687 list = g_list_first(dir_list);
689 dir_detail = (app2ext_dir_details *)list->data;
690 if (dir_detail && dir_detail->name
691 && dir_detail->type == APP2EXT_DIR_RO) {
692 ret = _app2sd_create_dir_with_link(application_path,
693 pkgid, dir_detail->name, uid);
697 list = g_list_next(list);
699 return APP2EXT_SUCCESS;
702 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
703 const char *dev, int mount_type, GList *dir_list,
704 app2sd_cmd cmd, uid_t uid)
706 int ret = APP2EXT_SUCCESS;
708 char application_mmc_path[FILENAME_MAX] = { 0, };
709 char temp_path[FILENAME_MAX] = { 0, };
710 char err_buf[1024] = {0,};
711 struct timespec time = {
713 .tv_nsec = 1000 * 1000 * 200
717 _E("input param is NULL (%s)",
719 return APP2EXT_ERROR_INVALID_ARGUMENTS;
722 /* check directory existence */
723 fd = open(application_path, O_RDONLY|O_DIRECTORY);
725 _E("path(%s) error(%d)", application_path, errno);
726 return APP2EXT_ERROR_OPEN_DIR;
730 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
732 fd = open(application_mmc_path, O_RDONLY|O_DIRECTORY);
734 _E("path(%s) error(%d)", application_mmc_path, errno);
735 return APP2EXT_ERROR_OPEN_DIR;
739 nanosleep(&time, NULL); /* 200ms sleep */
740 _D("give a delay for mount");
742 switch (mount_type) {
744 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
745 MS_MGC_VAL | MS_RDONLY | MS_NOSUID, NULL)) < 0) {
746 _E("read only mount failed, " \
748 "dev is (%s) path is (%s)",
749 errno, dev, application_mmc_path);
750 ret = APP2EXT_ERROR_MOUNT;
754 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
755 MS_MGC_VAL | MS_NOSUID, NULL)) < 0) {
756 _E("read write mount failed, " \
757 "errono is (%d)", errno);
758 ret = APP2EXT_ERROR_MOUNT;
761 case MOUNT_TYPE_RW_NOEXEC:
762 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
763 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID, NULL)) < 0) {
764 _E("rwnx mount failed " \
765 "errono is (%d)", errno);
766 ret = APP2EXT_ERROR_MOUNT;
769 case MOUNT_TYPE_RD_REMOUNT:
770 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
771 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT | MS_NOSUID,
773 _E("read remount failed "
774 "errono is (%d)", errno);
775 ret = APP2EXT_ERROR_MOUNT;
778 case MOUNT_TYPE_RW_REMOUNT:
779 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
780 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID, NULL)) < 0) {
781 _E("read write remount failed "
782 "errono(%d), errstr(%s)", errno,
783 strerror_r(errno, err_buf, sizeof(err_buf)));
784 ret = APP2EXT_ERROR_MOUNT;
788 _E("invalid mount type");
792 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
793 cmd == APP2SD_PRE_UPGRADE) {
794 ret = _app2sd_create_directory_entry(application_path,
795 pkgid, dir_list, uid);
798 /* change lost+found permission */
799 snprintf(temp_path, FILENAME_MAX - 1, "%s/lost+found",
800 application_mmc_path);
801 ret = _app2sd_make_directory(temp_path, uid);
803 _E("create directory(%s) failed", temp_path);
804 return APP2EXT_ERROR_CREATE_DIRECTORY;
810 int _app2sd_unmount_app_content(const char *application_path)
812 int ret = APP2EXT_SUCCESS;
813 char application_dir_mmc_path[FILENAME_MAX] = { 0, };
814 char err_buf[1024] = {0,};
816 snprintf(application_dir_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
818 if ((ret = umount(application_dir_mmc_path)) < 0) {
819 strerror_r(errno, err_buf, sizeof(err_buf));
820 _E("unable to umount the dir, ret(%d) error(%d, %s)",
821 ret, errno, err_buf);
827 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
829 int ret = APP2EXT_SUCCESS;
831 ret = _app2sd_copy_dir(src_path, arch_path);
832 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
833 char err_buf[1024] = {0,};
834 strerror_r(errno, err_buf, sizeof(err_buf));
835 _E("unable to copy from (%s) to (%s), err is (%s)",
836 src_path, arch_path, err_buf);
837 return APP2EXT_ERROR_MOVE;
840 ret = _app2sd_delete_directory((char *)src_path);
842 _E("unable to delete (%s)", src_path);
843 return APP2EXT_ERROR_DELETE_DIRECTORY;
849 int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list, uid_t uid)
851 int ret = APP2EXT_SUCCESS;
852 mode_t mode = DIR_PERMS;
853 char temp_dir_path[FILENAME_MAX] = { 0, };
854 char application_mmc_path[FILENAME_MAX] = { 0, };
855 char application_archive_path[FILENAME_MAX] = { 0, };
856 char application_path[FILENAME_MAX] = { 0, };
857 char loopback_device[FILENAME_MAX] = { 0, };
858 unsigned long long total_size = 0;
860 int reqd_disk_size = 0;
861 char *device_node = NULL;
862 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
865 int free_mmc_mem = 0;
868 app2ext_dir_details *dir_detail = NULL;
869 char err_buf[1024] = { 0,};
870 char *encoded_id = NULL;
872 /* check whether MMC is present or not */
873 ret = _app2sd_check_mmc_status();
875 _E("MMC not preset OR Not ready(%d)", ret);
876 return APP2EXT_ERROR_MMC_STATUS;
879 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
880 if (encoded_id == NULL)
881 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
883 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
884 APP2SD_PATH, encoded_id);
886 if (_is_global(uid)) {
887 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
888 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
890 tzplatform_set_user(uid);
891 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
892 tzplatform_getenv(TZ_USER_APP), pkgid);
893 tzplatform_reset_user();
896 /* check whether application is in external memory or not */
897 fp = fopen(loopback_device, "r+");
899 _W("Already %s entry is present in the SD Card, " \
900 "delete entry and go on without return", pkgid);
902 _app2sd_force_clean(pkgid, application_path, loopback_device, uid);
905 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
907 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
910 ret = mkdir(application_mmc_path, mode);
912 if (errno != EEXIST) {
913 _E("unable to create directory for archiving," \
914 " error(%d)", errno);
915 return APP2EXT_ERROR_CREATE_DIRECTORY;
919 ret = mkdir(application_archive_path, mode);
921 if (errno != EEXIST) {
922 _E("unable to create directory for archiving," \
923 " error(%d)", errno);
924 return APP2EXT_ERROR_CREATE_DIRECTORY;
928 list = g_list_first(dir_list);
930 dir_detail = (app2ext_dir_details *)list->data;
931 if (dir_detail && dir_detail->name
932 && dir_detail->type == APP2EXT_DIR_RO) {
933 memset(temp_dir_path, '\0', FILENAME_MAX);
934 snprintf(temp_dir_path, FILENAME_MAX,
935 "%s/%s", application_path,
937 _D("cal size of app dirs, temp_dir_path(%s)",
940 _app2sd_calculate_dir_size(temp_dir_path);
942 list = g_list_next(list);
945 reqd_size = ((total_size) / (1024 * 1024)) + 2;
946 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
948 /* find avialable free memory in the MMC card */
949 ret = _app2sd_get_available_free_memory(MMC_PATH, &free_mmc_mem);
951 _E("unable to get available free memory in MMC (%d)", ret);
952 return APP2EXT_ERROR_MMC_STATUS;
954 /* if avaialalbe free memory in MMC is less than
955 * required size + 5MB, return error
957 if (reqd_disk_size > free_mmc_mem) {
958 _E("insufficient memory in MMC for application installation (%d)",
960 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
962 /* create a loopback device */
963 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
964 (reqd_disk_size + PKG_BUF_SIZE));
966 _E("loopback node creation failed");
970 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
971 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
973 _E("dmcrypt setup device error(%d)", ret);
974 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
977 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
980 _E("dmcrypt open device error");
981 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
984 /* perform loopback encryption setup */
985 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
986 loopback_device, uid);
988 _E("loopback encryption setup failed");
989 return APP2EXT_ERROR_DO_LOSETUP;
991 _D("device_node (%s)", device_node);
992 /* check whether loopback device is associated with device node or not */
993 devi = _app2sd_find_associated_device_node(loopback_device);
995 _E("finding associated device node failed");
996 ret = APP2EXT_ERROR_DO_LOSETUP;
1003 /* format the loopback file system */
1004 ret = _app2sd_create_file_system(device_node);
1006 _E("create ext4 filesystem failed");
1007 ret = APP2EXT_ERROR_CREATE_FS;
1011 list = g_list_first(dir_list);
1013 dir_detail = (app2ext_dir_details *)list->data;
1014 if (dir_detail && dir_detail->name
1015 && dir_detail->type == APP2EXT_DIR_RO) {
1016 memset(temp_dir_path, '\0', FILENAME_MAX);
1017 snprintf(temp_dir_path, FILENAME_MAX,
1018 "%s/%s", application_path,
1020 _D("app2archive, temp_dir_path(%s)",
1022 ret = _app2sd_move_to_archive(temp_dir_path,
1023 application_archive_path);
1025 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1026 _E("unable to access (%s)",
1029 _E("unable to copy from (%s) to (%s)",
1031 application_archive_path);
1036 list = g_list_next(list);
1039 /* mount the loopback encrypted pseudo device on application installation path
1040 * as with Read Write permission
1042 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
1043 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
1049 list = g_list_first(dir_list);
1051 dir_detail = (app2ext_dir_details *)list->data;
1052 if (dir_detail && dir_detail->name
1053 && dir_detail->type == APP2EXT_DIR_RO) {
1054 memset(temp_dir_path, '\0', FILENAME_MAX);
1055 snprintf(temp_dir_path, FILENAME_MAX,
1056 "%s/%s", application_archive_path,
1058 _D("archive2mmc, temp_dir_path(%s)",
1060 ret = _app2sd_copy_dir(temp_dir_path,
1061 application_mmc_path);
1063 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1064 _E("unable to access (%s)",
1068 err_buf, sizeof(err_buf));
1069 _E("unable to copy from (%s) to (%s)," \
1072 application_mmc_path, err_buf);
1076 ret = _app2sd_delete_directory(temp_dir_path);
1078 _E("unable to delete (%s)", temp_dir_path);
1082 list = g_list_next(list);
1085 ret = _app2sd_delete_directory(application_archive_path);
1087 _E("unable to delete (%s)", application_archive_path);
1088 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
1093 return APP2EXT_SUCCESS;
1104 int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list, uid_t uid)
1106 int ret = APP2EXT_SUCCESS;
1107 mode_t mode = DIR_PERMS;
1108 char temp_dir_path[FILENAME_MAX] = { 0, };
1109 char application_mmc_path[FILENAME_MAX] = { 0, };
1110 char application_archive_path[FILENAME_MAX] = { 0, };
1111 char application_path[FILENAME_MAX] = { 0, };
1112 char loopback_device[FILENAME_MAX] = { 0, };
1113 char *device_node = NULL;
1116 app2ext_dir_details *dir_detail = NULL;
1118 int free_internal_mem = 0;
1119 struct statvfs buf = {0,};
1120 unsigned long long temp = 0;
1121 char err_buf[1024] = {0,};
1122 char *encoded_id = NULL;
1124 /* check whether MMC is present or not */
1125 ret = _app2sd_check_mmc_status();
1127 _E("MMC not preset OR Not ready(%d)", ret);
1128 return APP2EXT_ERROR_MMC_STATUS;
1131 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1132 if (encoded_id == NULL)
1133 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1135 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1136 APP2SD_PATH, encoded_id);
1138 if (_is_global(uid)) {
1139 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1140 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1142 tzplatform_set_user(uid);
1143 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1144 tzplatform_getenv(TZ_USER_APP), pkgid);
1145 tzplatform_reset_user();
1148 /* check whether application is in external memory or not */
1149 fp = fopen(loopback_device, "r+");
1151 _E("application (%s) is not installed on SD Card",
1153 return APP2EXT_ERROR_FILE_ABSENT;
1159 memset((void *)&buf, '\0', sizeof(struct statvfs));
1160 ret = statvfs(INTERNAL_STORAGE_PATH, &buf);
1162 temp = (buf.f_bsize * buf.f_bavail) / (1024 * 1024);
1163 free_internal_mem = (int)temp;
1165 _E("unable to get internal storage size");
1166 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1169 fp = fopen(loopback_device, "r+");
1171 _E("app entry is not present in SD card");
1172 return APP2EXT_ERROR_INVALID_PACKAGE;
1176 /* get installed app size*/
1177 temp = _app2sd_calculate_file_size(loopback_device);
1178 reqd_size = (int)((temp) / (1024 * 1024));
1179 _D("reqd size is (%d)", reqd_size);
1181 if (reqd_size == 0) {
1182 _E("app entry is not present in SD Card");
1183 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1186 _D("reqd size: (%d)MB, free internal mem: (%d)MB",
1187 reqd_size, free_internal_mem);
1189 /* if avaialalbe free memory in internal storage is
1190 * less than required size, return error
1192 if (reqd_size > free_internal_mem) {
1193 _E("innsufficient memory in internal storage" \
1194 " for application installation (%d)", ret);
1195 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1198 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1200 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1202 device_node = _app2sd_find_associated_device_node(loopback_device);
1204 if (NULL == device_node) {
1205 /* do loopback setup */
1206 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1207 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1208 false, uid, &device_node);
1210 _E("dmcrypt open device error(%d)", ret);
1211 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1214 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1215 loopback_device, uid);
1216 if (device_node == NULL) {
1217 _E("loopback encryption setup failed");
1218 return APP2EXT_ERROR_DO_LOSETUP;
1222 ret = _app2sd_mount_app_content(application_path,
1223 pkgid, device_node, MOUNT_TYPE_RW,
1224 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1227 ret = APP2EXT_ERROR_MOUNT_PATH;
1231 /* do re-mounting */
1232 ret = _app2sd_mount_app_content(application_path,
1233 pkgid, device_node, MOUNT_TYPE_RW_REMOUNT,
1234 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1236 _E("re-mount failed");
1237 ret = APP2EXT_ERROR_MOUNT_PATH;
1242 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
1244 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
1247 ret = mkdir(application_archive_path, mode);
1249 if (errno != EEXIST) {
1250 _E("unable to create directory for archiving," \
1251 " error(%d)", errno);
1252 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
1257 list = g_list_first(dir_list);
1259 dir_detail = (app2ext_dir_details *)list->data;
1260 if (dir_detail && dir_detail->name
1261 && dir_detail->type == APP2EXT_DIR_RO) {
1262 /* archiving code */
1263 memset(temp_dir_path, '\0', FILENAME_MAX);
1264 snprintf(temp_dir_path, FILENAME_MAX,
1265 "%s/%s", application_mmc_path,
1267 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1268 ret = _app2sd_copy_dir(temp_dir_path,
1269 application_archive_path);
1271 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1272 _E("unable to access (%s)",
1276 err_buf, sizeof(err_buf));
1277 _E("unable to copy from (%s) to (%s),"
1280 application_archive_path, err_buf);
1285 /* delete the symbolic link files [bin, lib, res]*/
1286 memset(temp_dir_path, '\0', FILENAME_MAX);
1287 snprintf(temp_dir_path, FILENAME_MAX,
1288 "%s/%s", application_path,
1290 _D("unlink, temp_dir_path(%s)", temp_dir_path);
1291 ret = unlink(temp_dir_path);
1293 if (errno == ENOENT) {
1294 _E("directory (%s) does not exist",
1297 _E("unable to remove the symbolic link file (%s)," \
1298 " it is already unlinked",
1304 /* Copy content to destination */
1305 memset(temp_dir_path, '\0', FILENAME_MAX);
1306 snprintf(temp_dir_path, FILENAME_MAX,
1307 "%s/%s", application_archive_path,
1309 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1310 ret = _app2sd_copy_dir(temp_dir_path, application_path);
1312 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1313 _E("unable to access (%s)",
1317 err_buf, sizeof(err_buf));
1318 _E("unable to copy from (%s) to (%s) " \
1321 application_path, err_buf);
1326 list = g_list_next(list);
1329 _D("copying file completed");
1330 ret = _app2sd_unmount_app_content(application_path);
1332 _E("unable to unmount SD directory for app (%s)",
1335 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1336 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1338 _E("close dmcrypt device error(%d)", ret);
1340 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1342 _E("unable to detach loopback setup for (%s)",
1346 ret = _app2sd_delete_loopback_device(loopback_device);
1348 _E("unable to delete the loopback device for (%s)",
1351 ret = _app2sd_delete_directory(application_mmc_path);
1353 _E("unable to delete (%s)", application_mmc_path);
1355 ret = _app2sd_delete_directory(application_archive_path);
1357 _E("unable to delete (%s)", application_archive_path);
1359 /* remove passwrd from DB */
1360 ret = _app2sd_initialize_db();
1362 _E("app2sd db initialize failed");
1364 ret = _app2sd_remove_info_from_db(pkgid, uid);
1366 _E("cannot remove info from db");
1368 return APP2EXT_SUCCESS;
1379 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1380 GList *dir_list, uid_t uid)
1382 int ret = APP2EXT_SUCCESS;
1384 /* Check whether MMC is present or not */
1385 ret = _app2sd_check_mmc_status();
1387 _E("MMC not preset OR Not ready(%d)", ret);
1388 return APP2EXT_ERROR_MMC_STATUS;
1391 switch (move_type) {
1392 case APP2EXT_MOVE_TO_EXT:
1393 ret = _app2sd_move_app_to_external(pkgid, dir_list, uid);
1395 _E("move app to external memory failed(%d)", ret);
1399 case APP2EXT_MOVE_TO_PHONE:
1400 ret = _app2sd_move_app_to_internal(pkgid, dir_list, uid);
1402 _E("move app to internal memory failed(%d)", ret);
1407 _E("invalid argument");
1408 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1414 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1416 char path[FILENAME_MAX] = { 0, };
1417 int ret = APP2EXT_SUCCESS;
1419 app2ext_dir_details *dir_detail = NULL;
1421 list = g_list_first(dir_list);
1423 dir_detail = (app2ext_dir_details *)list->data;
1424 if (dir_detail && dir_detail->name
1425 && dir_detail->type == APP2EXT_DIR_RO) {
1426 memset((void *)&path, '\0', FILENAME_MAX);
1427 snprintf(path, FILENAME_MAX - 1, "%s/%s", src,
1429 ret = _app2sd_copy_dir(path, dest);
1431 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1432 _E("unable to access (%s)", path);
1434 _E("unable to copy from (%s) " \
1435 "to (%s), errno is (%d)",
1437 return APP2EXT_ERROR_MOVE;
1441 list = g_list_next(list);
1444 return APP2EXT_SUCCESS;
1447 int _app2sd_duplicate_device(const char *pkgid,
1448 const char *loopback_device,
1449 const char *temp_pkgid,
1450 const char *temp_application_path,
1451 const char *temp_loopback_device,
1452 GList *dir_list, char *dev_node, int size,
1457 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1459 char *result = NULL;
1460 char *passwd = NULL;
1463 /* create a new loopback device */
1464 ret = _app2sd_create_loopback_device(temp_pkgid,
1465 temp_loopback_device, (size + PKG_BUF_SIZE));
1467 _E("package already present");
1471 /* perform loopback encryption setup */
1472 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1473 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1474 temp_loopback_device, uid);
1476 _E("dmcrypt duplicate encryption setup failed");
1477 _app2sd_delete_loopback_device(temp_loopback_device);
1478 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1481 /* get password for loopback encryption */
1482 ret = _app2sd_initialize_db();
1484 _E("app2sd db initialize failed");
1485 return APP2EXT_ERROR_DB_INITIALIZE;
1488 if ((passwd = _app2sd_get_password_from_db(pkgid, uid)) == NULL) {
1489 passwd = (char *)_app2sd_generate_password(pkgid);
1490 if (NULL == passwd) {
1491 _E("unable to generate password");
1492 return APP2EXT_ERROR_PASSWD_GENERATION;
1494 if ((ret = _app2sd_set_info_in_db(pkgid,
1495 passwd, loopback_device, uid)) < 0) {
1496 _E("unable to save info");
1499 return APP2EXT_ERROR_SQLITE_REGISTRY;
1504 dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1505 temp_pkgid, temp_loopback_device, passwd, uid);
1507 _E("losetup failed, device node is (%s)", dev_node);
1508 _app2sd_delete_loopback_device(temp_loopback_device);
1511 return APP2EXT_ERROR_DO_LOSETUP;
1515 _D("duplicate setup SUCCESS");
1517 /* check whether loopback device is associated with
1518 * device node or not
1520 devi = _app2sd_find_associated_device_node(temp_loopback_device);
1522 _E("finding associated device node failed");
1523 err_res = APP2EXT_ERROR_DO_LOSETUP;
1526 _D("losetup SUCCESS");
1529 /* format the loopback file system */
1530 ret = _app2sd_create_file_system(dev_node);
1532 _E("creating fs failed");
1533 err_res = APP2EXT_ERROR_CREATE_FS;
1536 _D("create filesystem SUCCESS");
1538 /* do mounting for new dev*/
1539 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1540 dev_node, MOUNT_TYPE_RW, dir_list,
1541 APP2SD_PRE_UPGRADE, uid);
1543 _E("remount failed");
1544 err_res = APP2EXT_ERROR_MOUNT_PATH;
1548 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1555 return APP2EXT_SUCCESS;
1559 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1560 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1562 _E("close dmcrypt device error(%d)", ret);
1564 result = _app2sd_detach_loop_device(dev_node);
1570 _app2sd_delete_loopback_device(temp_loopback_device);
1578 int _app2sd_update_loopback_device_size(const char *pkgid,
1579 const char *loopback_device,
1580 const char *application_path,
1581 const char *temp_pkgid,
1582 const char *temp_loopback_device,
1583 const char *temp_application_path,
1584 int size, GList *dir_list,
1588 char *device_node = NULL;
1589 char *old_device_node = NULL;
1591 char application_mmc_path[FILENAME_MAX] = { 0, };
1592 char temp_application_mmc_path[FILENAME_MAX] = { 0, };
1594 ret = _app2sd_duplicate_device(pkgid, loopback_device,
1595 temp_pkgid, temp_application_path, temp_loopback_device,
1596 dir_list, device_node, size, uid);
1598 _E("creating duplicate device failed");
1602 /* get the associated device node for SD card applicatione */
1603 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1605 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1607 old_device_node = _app2sd_find_associated_device_node(loopback_device);
1609 if (NULL == old_device_node) {
1610 /* do loopback setup */
1611 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1612 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1613 false, uid, &old_device_node);
1615 _E("dmcrypt open device error");
1616 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1620 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1621 loopback_device, uid);
1622 if (old_device_node == NULL) {
1623 _E("loopback encryption setup failed");
1624 err_res = APP2EXT_ERROR_DO_LOSETUP;
1629 ret = _app2sd_mount_app_content(application_path, pkgid,
1630 old_device_node, MOUNT_TYPE_RW, dir_list,
1631 APP2SD_PRE_UPGRADE, uid);
1633 _E("remount failed");
1634 err_res = APP2EXT_ERROR_MOUNT_PATH;
1637 /* do re-mounting */
1638 ret = _app2sd_mount_app_content(application_path, pkgid,
1639 old_device_node, MOUNT_TYPE_RW_REMOUNT, dir_list,
1640 APP2SD_PRE_UPGRADE, uid);
1642 _E("remount failed");
1643 err_res = APP2EXT_ERROR_MOUNT_PATH;
1647 snprintf(application_mmc_path, FILENAME_MAX - 1,
1648 "%s/.mmc", application_path);
1649 snprintf(temp_application_mmc_path, FILENAME_MAX - 1,
1650 "%s/.mmc", temp_application_path);
1652 ret = _app2sd_copy_ro_content(application_mmc_path,
1653 temp_application_mmc_path, dir_list);
1655 _E("copy ro content failed");
1659 ret = _app2sd_unmount_app_content(application_path);
1661 _E("unable to unmount the SD application");
1662 err_res = APP2EXT_ERROR_UNMOUNT;
1665 ret = _app2sd_unmount_app_content(temp_application_path);
1667 _E("unable to unmount the SD application");
1668 err_res = APP2EXT_ERROR_UNMOUNT;
1672 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1673 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1675 _E("close dmcrypt device error(%d)", ret);
1676 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1680 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1682 _E("close dmcrypt device error(%d)", ret);
1683 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1687 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1689 _E("unable to remove loopback setup");
1690 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1693 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1695 _E("unable to remove loopback setup");
1696 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1701 ret = _app2sd_delete_directory(loopback_device);
1703 _E("unable to delete (%s)", loopback_device);
1704 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1708 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1710 _E("unable to rename (%s)", temp_loopback_device);
1711 err_res = APP2EXT_ERROR_MOVE;
1715 ret = _app2sd_delete_directory(temp_application_path);
1717 _E("unable to delete (%s)", temp_application_path);
1718 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1722 return APP2EXT_SUCCESS;
1725 if (old_device_node) {
1726 free(old_device_node);
1727 old_device_node = NULL;
1730 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1731 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1733 _E("close dmcrypt device error(%d)", ret);
1735 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1738 _E("close dmcrypt device error(%d)", ret);
1740 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1742 _E("unable to remove loopback setup");
1744 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1746 _E("unable to remove loopback setup");
1749 _app2sd_delete_loopback_device(temp_loopback_device);
1751 ret = _app2sd_delete_directory(temp_application_path);
1753 _E("unable to delete (%s)", temp_application_path);
1758 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1759 const char *loopback_device, uid_t uid)
1761 int ret = APP2EXT_SUCCESS;
1763 /* unmount the loopback encrypted pseudo device from the application installation path */
1764 ret = _app2sd_unmount_app_content(application_path);
1766 _E("unable to unmount the app content (%d)", ret);
1768 /* detach the loopback encryption setup for the application */
1769 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1770 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1772 _E("close dmcrypt device error (%d)", ret);
1774 ret = _app2sd_remove_all_loopback_encryption_setups(loopback_device);
1776 _E("unable to detach the loopback encryption setup for the application");
1779 /* delete the loopback device from the SD card */
1780 ret = _app2sd_delete_loopback_device(loopback_device);
1782 _E("unable to detach the loopback encryption setup for the application");
1784 /* delete symlink */
1785 _app2sd_delete_symlink(application_path);
1787 /* remove passwrd from DB */
1788 ret = _app2sd_initialize_db();
1790 _E("app2sd db initialize failed");
1792 ret = _app2sd_remove_info_from_db(pkgid, uid);
1794 _E("cannot remove info from db");