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_UNINSTALL || cmd == APP2SD_MOVE_APP_TO_PHONE ||
793 cmd == APP2SD_PRE_UPGRADE) {
794 /* delete lost+found dir */
795 snprintf(temp_path, FILENAME_MAX - 1, "%s/lost+found",
796 application_mmc_path);
797 ret = _app2sd_delete_directory(temp_path);
799 _E("unable to delete (%s)", temp_path);
800 return APP2EXT_ERROR_DELETE_DIRECTORY;
804 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
805 cmd == APP2SD_PRE_UPGRADE) {
806 ret = _app2sd_create_directory_entry(application_path,
807 pkgid, dir_list, uid);
813 int _app2sd_unmount_app_content(const char *application_path)
815 int ret = APP2EXT_SUCCESS;
816 char application_dir_mmc_path[FILENAME_MAX] = { 0, };
817 char err_buf[1024] = {0,};
819 snprintf(application_dir_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
821 if ((ret = umount(application_dir_mmc_path)) < 0) {
822 strerror_r(errno, err_buf, sizeof(err_buf));
823 _E("unable to umount the dir, ret(%d) error(%d, %s)",
824 ret, errno, err_buf);
830 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
832 int ret = APP2EXT_SUCCESS;
834 ret = _app2sd_copy_dir(src_path, arch_path);
835 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
836 char err_buf[1024] = {0,};
837 strerror_r(errno, err_buf, sizeof(err_buf));
838 _E("unable to copy from (%s) to (%s), err is (%s)",
839 src_path, arch_path, err_buf);
840 return APP2EXT_ERROR_MOVE;
843 ret = _app2sd_delete_directory((char *)src_path);
845 _E("unable to delete (%s)", src_path);
846 return APP2EXT_ERROR_DELETE_DIRECTORY;
852 int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list, uid_t uid)
854 int ret = APP2EXT_SUCCESS;
855 mode_t mode = DIR_PERMS;
856 char temp_dir_path[FILENAME_MAX] = { 0, };
857 char application_mmc_path[FILENAME_MAX] = { 0, };
858 char application_archive_path[FILENAME_MAX] = { 0, };
859 char application_path[FILENAME_MAX] = { 0, };
860 char loopback_device[FILENAME_MAX] = { 0, };
861 unsigned long long total_size = 0;
863 int reqd_disk_size = 0;
864 char *device_node = NULL;
865 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
868 int free_mmc_mem = 0;
871 app2ext_dir_details *dir_detail = NULL;
872 char err_buf[1024] = { 0,};
873 char *encoded_id = NULL;
875 /* check whether MMC is present or not */
876 ret = _app2sd_check_mmc_status();
878 _E("MMC not preset OR Not ready(%d)", ret);
879 return APP2EXT_ERROR_MMC_STATUS;
882 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
883 if (encoded_id == NULL)
884 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
886 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
887 APP2SD_PATH, encoded_id);
889 if (_is_global(uid)) {
890 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
891 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
893 tzplatform_set_user(uid);
894 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
895 tzplatform_getenv(TZ_USER_APP), pkgid);
896 tzplatform_reset_user();
899 /* check whether application is in external memory or not */
900 fp = fopen(loopback_device, "r+");
902 _W("Already %s entry is present in the SD Card, " \
903 "delete entry and go on without return", pkgid);
905 _app2sd_force_clean(pkgid, application_path, loopback_device, uid);
908 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
910 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
913 ret = mkdir(application_archive_path, mode);
915 if (errno != EEXIST) {
916 _E("unable to create directory for archiving," \
917 " error(%d)", errno);
918 return APP2EXT_ERROR_CREATE_DIRECTORY;
922 list = g_list_first(dir_list);
924 dir_detail = (app2ext_dir_details *)list->data;
925 if (dir_detail && dir_detail->name
926 && dir_detail->type == APP2EXT_DIR_RO) {
927 memset(temp_dir_path, '\0', FILENAME_MAX);
928 snprintf(temp_dir_path, FILENAME_MAX,
929 "%s/%s", application_path,
931 _D("cal size of app dirs, temp_dir_path(%s)",
934 _app2sd_calculate_dir_size(temp_dir_path);
936 list = g_list_next(list);
939 reqd_size = ((total_size) / (1024 * 1024)) + 2;
940 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
942 /* find avialable free memory in the MMC card */
943 ret = _app2sd_get_available_free_memory(MMC_PATH, &free_mmc_mem);
945 _E("unable to get available free memory in MMC (%d)", ret);
946 return APP2EXT_ERROR_MMC_STATUS;
948 /* if avaialalbe free memory in MMC is less than
949 * required size + 5MB, return error
951 if (reqd_disk_size > free_mmc_mem) {
952 _E("insufficient memory in MMC for application installation (%d)",
954 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
956 /* create a loopback device */
957 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
958 (reqd_disk_size + PKG_BUF_SIZE));
960 _E("loopback node creation failed");
964 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
965 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
967 _E("dmcrypt setup device error(%d)", ret);
968 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
971 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
974 _E("dmcrypt open device error");
975 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
978 /* perform loopback encryption setup */
979 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
980 loopback_device, uid);
982 _E("loopback encryption setup failed");
983 return APP2EXT_ERROR_DO_LOSETUP;
985 _D("device_node (%s)", device_node);
986 /* check whether loopback device is associated with device node or not */
987 devi = _app2sd_find_associated_device_node(loopback_device);
989 _E("finding associated device node failed");
990 ret = APP2EXT_ERROR_DO_LOSETUP;
997 /* format the loopback file system */
998 ret = _app2sd_create_file_system(device_node);
1000 _E("create ext4 filesystem failed");
1001 ret = APP2EXT_ERROR_CREATE_FS;
1005 list = g_list_first(dir_list);
1007 dir_detail = (app2ext_dir_details *)list->data;
1008 if (dir_detail && dir_detail->name
1009 && dir_detail->type == APP2EXT_DIR_RO) {
1010 memset(temp_dir_path, '\0', FILENAME_MAX);
1011 snprintf(temp_dir_path, FILENAME_MAX,
1012 "%s/%s", application_path,
1014 _D("app2archive, temp_dir_path(%s)",
1016 ret = _app2sd_move_to_archive(temp_dir_path,
1017 application_archive_path);
1019 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1020 _E("unable to access (%s)",
1023 _E("unable to copy from (%s) to (%s)",
1025 application_archive_path);
1030 list = g_list_next(list);
1033 /* mount the loopback encrypted pseudo device on application installation path
1034 * as with Read Write permission
1036 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
1037 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
1043 list = g_list_first(dir_list);
1045 dir_detail = (app2ext_dir_details *)list->data;
1046 if (dir_detail && dir_detail->name
1047 && dir_detail->type == APP2EXT_DIR_RO) {
1048 memset(temp_dir_path, '\0', FILENAME_MAX);
1049 snprintf(temp_dir_path, FILENAME_MAX,
1050 "%s/%s", application_archive_path,
1052 _D("archive2mmc, temp_dir_path(%s)",
1054 ret = _app2sd_copy_dir(temp_dir_path,
1055 application_mmc_path);
1057 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1058 _E("unable to access (%s)",
1062 err_buf, sizeof(err_buf));
1063 _E("unable to copy from (%s) to (%s)," \
1066 application_mmc_path, err_buf);
1070 ret = _app2sd_delete_directory(temp_dir_path);
1072 _E("unable to delete (%s)", temp_dir_path);
1076 list = g_list_next(list);
1079 ret = _app2sd_delete_directory(application_archive_path);
1081 _E("unable to delete (%s)", application_archive_path);
1082 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
1087 return APP2EXT_SUCCESS;
1098 int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list, uid_t uid)
1100 int ret = APP2EXT_SUCCESS;
1101 mode_t mode = DIR_PERMS;
1102 char temp_dir_path[FILENAME_MAX] = { 0, };
1103 char application_mmc_path[FILENAME_MAX] = { 0, };
1104 char application_archive_path[FILENAME_MAX] = { 0, };
1105 char application_path[FILENAME_MAX] = { 0, };
1106 char loopback_device[FILENAME_MAX] = { 0, };
1107 char *device_node = NULL;
1110 app2ext_dir_details *dir_detail = NULL;
1112 int free_internal_mem = 0;
1113 struct statvfs buf = {0,};
1114 unsigned long long temp = 0;
1115 char err_buf[1024] = {0,};
1116 char *encoded_id = NULL;
1118 /* check whether MMC is present or not */
1119 ret = _app2sd_check_mmc_status();
1121 _E("MMC not preset OR Not ready(%d)", ret);
1122 return APP2EXT_ERROR_MMC_STATUS;
1125 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1126 if (encoded_id == NULL)
1127 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1129 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1130 APP2SD_PATH, encoded_id);
1132 if (_is_global(uid)) {
1133 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1134 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1136 tzplatform_set_user(uid);
1137 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1138 tzplatform_getenv(TZ_USER_APP), pkgid);
1139 tzplatform_reset_user();
1142 /* check whether application is in external memory or not */
1143 fp = fopen(loopback_device, "r+");
1145 _E("application (%s) is not installed on SD Card",
1147 return APP2EXT_ERROR_FILE_ABSENT;
1153 memset((void *)&buf, '\0', sizeof(struct statvfs));
1154 ret = statvfs(INTERNAL_STORAGE_PATH, &buf);
1156 temp = (buf.f_bsize * buf.f_bavail) / (1024 * 1024);
1157 free_internal_mem = (int)temp;
1159 _E("unable to get internal storage size");
1160 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1163 fp = fopen(loopback_device, "r+");
1165 _E("app entry is not present in SD card");
1166 return APP2EXT_ERROR_INVALID_PACKAGE;
1170 /* get installed app size*/
1171 temp = _app2sd_calculate_file_size(loopback_device);
1172 reqd_size = (int)((temp) / (1024 * 1024));
1173 _D("reqd size is (%d)", reqd_size);
1175 if (reqd_size == 0) {
1176 _E("app entry is not present in SD Card");
1177 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1180 _D("reqd size: (%d)MB, free internal mem: (%d)MB",
1181 reqd_size, free_internal_mem);
1183 /* if avaialalbe free memory in internal storage is
1184 * less than required size, return error
1186 if (reqd_size > free_internal_mem) {
1187 _E("innsufficient memory in internal storage" \
1188 " for application installation (%d)", ret);
1189 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1192 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1194 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1196 device_node = _app2sd_find_associated_device_node(loopback_device);
1198 if (NULL == device_node) {
1199 /* do loopback setup */
1200 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1201 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1202 false, uid, &device_node);
1204 _E("dmcrypt open device error(%d)", ret);
1205 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1208 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1209 loopback_device, uid);
1210 if (device_node == NULL) {
1211 _E("loopback encryption setup failed");
1212 return APP2EXT_ERROR_DO_LOSETUP;
1216 ret = _app2sd_mount_app_content(application_path,
1217 pkgid, device_node, MOUNT_TYPE_RW,
1218 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1221 ret = APP2EXT_ERROR_MOUNT_PATH;
1225 /* do re-mounting */
1226 ret = _app2sd_mount_app_content(application_path,
1227 pkgid, device_node, MOUNT_TYPE_RW_REMOUNT,
1228 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1230 _E("re-mount failed");
1231 ret = APP2EXT_ERROR_MOUNT_PATH;
1236 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
1238 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
1241 ret = mkdir(application_archive_path, mode);
1243 if (errno != EEXIST) {
1244 _E("unable to create directory for archiving," \
1245 " error(%d)", errno);
1246 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
1251 list = g_list_first(dir_list);
1253 dir_detail = (app2ext_dir_details *)list->data;
1254 if (dir_detail && dir_detail->name
1255 && dir_detail->type == APP2EXT_DIR_RO) {
1256 /* archiving code */
1257 memset(temp_dir_path, '\0', FILENAME_MAX);
1258 snprintf(temp_dir_path, FILENAME_MAX,
1259 "%s/%s", application_mmc_path,
1261 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1262 ret = _app2sd_copy_dir(temp_dir_path,
1263 application_archive_path);
1265 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1266 _E("unable to access (%s)",
1270 err_buf, sizeof(err_buf));
1271 _E("unable to copy from (%s) to (%s),"
1274 application_archive_path, err_buf);
1279 /* delete the symbolic link files [bin, lib, res]*/
1280 memset(temp_dir_path, '\0', FILENAME_MAX);
1281 snprintf(temp_dir_path, FILENAME_MAX,
1282 "%s/%s", application_path,
1284 _D("unlink, temp_dir_path(%s)", temp_dir_path);
1285 ret = unlink(temp_dir_path);
1287 if (errno == ENOENT) {
1288 _E("directory (%s) does not exist",
1291 _E("unable to remove the symbolic link file (%s)," \
1292 " it is already unlinked",
1298 /* Copy content to destination */
1299 memset(temp_dir_path, '\0', FILENAME_MAX);
1300 snprintf(temp_dir_path, FILENAME_MAX,
1301 "%s/%s", application_archive_path,
1303 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1304 ret = _app2sd_copy_dir(temp_dir_path, application_path);
1306 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1307 _E("unable to access (%s)",
1311 err_buf, sizeof(err_buf));
1312 _E("unable to copy from (%s) to (%s) " \
1315 application_path, err_buf);
1320 list = g_list_next(list);
1323 _D("copying file completed");
1324 ret = _app2sd_unmount_app_content(application_path);
1326 _E("unable to unmount SD directory for app (%s)",
1329 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1330 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1332 _E("close dmcrypt device error(%d)", ret);
1334 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1336 _E("unable to detach loopback setup for (%s)",
1340 ret = _app2sd_delete_loopback_device(loopback_device);
1342 _E("unable to delete the loopback device for (%s)",
1345 ret = _app2sd_delete_directory(application_mmc_path);
1347 _E("unable to delete (%s)", application_mmc_path);
1349 ret = _app2sd_delete_directory(application_archive_path);
1351 _E("unable to delete (%s)", application_archive_path);
1353 /* remove passwrd from DB */
1354 ret = _app2sd_initialize_db();
1356 _E("app2sd db initialize failed");
1358 ret = _app2sd_remove_info_from_db(pkgid, uid);
1360 _E("cannot remove info from db");
1362 return APP2EXT_SUCCESS;
1373 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1374 GList *dir_list, uid_t uid)
1376 int ret = APP2EXT_SUCCESS;
1378 /* Check whether MMC is present or not */
1379 ret = _app2sd_check_mmc_status();
1381 _E("MMC not preset OR Not ready(%d)", ret);
1382 return APP2EXT_ERROR_MMC_STATUS;
1385 switch (move_type) {
1386 case APP2EXT_MOVE_TO_EXT:
1387 ret = _app2sd_move_app_to_external(pkgid, dir_list, uid);
1389 _E("move app to external memory failed(%d)", ret);
1393 case APP2EXT_MOVE_TO_PHONE:
1394 ret = _app2sd_move_app_to_internal(pkgid, dir_list, uid);
1396 _E("move app to internal memory failed(%d)", ret);
1401 _E("invalid argument");
1402 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1408 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1410 char path[FILENAME_MAX] = { 0, };
1411 int ret = APP2EXT_SUCCESS;
1413 app2ext_dir_details *dir_detail = NULL;
1415 list = g_list_first(dir_list);
1417 dir_detail = (app2ext_dir_details *)list->data;
1418 if (dir_detail && dir_detail->name
1419 && dir_detail->type == APP2EXT_DIR_RO) {
1420 memset((void *)&path, '\0', FILENAME_MAX);
1421 snprintf(path, FILENAME_MAX - 1, "%s/%s", src,
1423 ret = _app2sd_copy_dir(path, dest);
1425 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1426 _E("unable to access (%s)", path);
1428 _E("unable to copy from (%s) " \
1429 "to (%s), errno is (%d)",
1431 return APP2EXT_ERROR_MOVE;
1435 list = g_list_next(list);
1438 return APP2EXT_SUCCESS;
1441 int _app2sd_duplicate_device(const char *pkgid,
1442 const char *loopback_device,
1443 const char *temp_pkgid,
1444 const char *temp_application_path,
1445 const char *temp_loopback_device,
1446 GList *dir_list, char *dev_node, int size,
1451 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1453 char *result = NULL;
1454 char *passwd = NULL;
1457 /* create a new loopback device */
1458 ret = _app2sd_create_loopback_device(temp_pkgid,
1459 temp_loopback_device, (size + PKG_BUF_SIZE));
1461 _E("package already present");
1465 /* perform loopback encryption setup */
1466 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1467 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1468 temp_loopback_device, uid);
1470 _E("dmcrypt duplicate encryption setup failed");
1471 _app2sd_delete_loopback_device(temp_loopback_device);
1472 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1475 /* get password for loopback encryption */
1476 ret = _app2sd_initialize_db();
1478 _E("app2sd db initialize failed");
1479 return APP2EXT_ERROR_DB_INITIALIZE;
1482 if ((passwd = _app2sd_get_password_from_db(pkgid, uid)) == NULL) {
1483 passwd = (char *)_app2sd_generate_password(pkgid);
1484 if (NULL == passwd) {
1485 _E("unable to generate password");
1486 return APP2EXT_ERROR_PASSWD_GENERATION;
1488 if ((ret = _app2sd_set_info_in_db(pkgid,
1489 passwd, loopback_device, uid)) < 0) {
1490 _E("unable to save info");
1493 return APP2EXT_ERROR_SQLITE_REGISTRY;
1498 dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1499 temp_pkgid, temp_loopback_device, passwd, uid);
1501 _E("losetup failed, device node is (%s)", dev_node);
1502 _app2sd_delete_loopback_device(temp_loopback_device);
1505 return APP2EXT_ERROR_DO_LOSETUP;
1509 _D("duplicate setup SUCCESS");
1511 /* check whether loopback device is associated with
1512 * device node or not
1514 devi = _app2sd_find_associated_device_node(temp_loopback_device);
1516 _E("finding associated device node failed");
1517 err_res = APP2EXT_ERROR_DO_LOSETUP;
1520 _D("losetup SUCCESS");
1523 /* format the loopback file system */
1524 ret = _app2sd_create_file_system(dev_node);
1526 _E("creating fs failed");
1527 err_res = APP2EXT_ERROR_CREATE_FS;
1530 _D("create filesystem SUCCESS");
1532 /* do mounting for new dev*/
1533 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1534 dev_node, MOUNT_TYPE_RW, dir_list,
1535 APP2SD_PRE_UPGRADE, uid);
1537 _E("remount failed");
1538 err_res = APP2EXT_ERROR_MOUNT_PATH;
1542 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1549 return APP2EXT_SUCCESS;
1553 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1554 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1556 _E("close dmcrypt device error(%d)", ret);
1558 result = _app2sd_detach_loop_device(dev_node);
1564 _app2sd_delete_loopback_device(temp_loopback_device);
1572 int _app2sd_update_loopback_device_size(const char *pkgid,
1573 const char *loopback_device,
1574 const char *application_path,
1575 const char *temp_pkgid,
1576 const char *temp_loopback_device,
1577 const char *temp_application_path,
1578 int size, GList *dir_list,
1582 char *device_node = NULL;
1583 char *old_device_node = NULL;
1585 char application_mmc_path[FILENAME_MAX] = { 0, };
1586 char temp_application_mmc_path[FILENAME_MAX] = { 0, };
1588 ret = _app2sd_duplicate_device(pkgid, loopback_device,
1589 temp_pkgid, temp_application_path, temp_loopback_device,
1590 dir_list, device_node, size, uid);
1592 _E("creating duplicate device failed");
1596 /* get the associated device node for SD card applicatione */
1597 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1599 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1601 old_device_node = _app2sd_find_associated_device_node(loopback_device);
1603 if (NULL == old_device_node) {
1604 /* do loopback setup */
1605 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1606 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1607 false, uid, &old_device_node);
1609 _E("dmcrypt open device error");
1610 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1614 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1615 loopback_device, uid);
1616 if (old_device_node == NULL) {
1617 _E("loopback encryption setup failed");
1618 err_res = APP2EXT_ERROR_DO_LOSETUP;
1623 ret = _app2sd_mount_app_content(application_path, pkgid,
1624 old_device_node, MOUNT_TYPE_RW, dir_list,
1625 APP2SD_PRE_UPGRADE, uid);
1627 _E("remount failed");
1628 err_res = APP2EXT_ERROR_MOUNT_PATH;
1631 /* do re-mounting */
1632 ret = _app2sd_mount_app_content(application_path, pkgid,
1633 old_device_node, MOUNT_TYPE_RW_REMOUNT, dir_list,
1634 APP2SD_PRE_UPGRADE, uid);
1636 _E("remount failed");
1637 err_res = APP2EXT_ERROR_MOUNT_PATH;
1641 snprintf(application_mmc_path, FILENAME_MAX - 1,
1642 "%s/.mmc", application_path);
1643 snprintf(temp_application_mmc_path, FILENAME_MAX - 1,
1644 "%s/.mmc", temp_application_path);
1646 ret = _app2sd_copy_ro_content(application_mmc_path,
1647 temp_application_mmc_path, dir_list);
1649 _E("copy ro content failed");
1653 ret = _app2sd_unmount_app_content(application_path);
1655 _E("unable to unmount the SD application");
1656 err_res = APP2EXT_ERROR_UNMOUNT;
1659 ret = _app2sd_unmount_app_content(temp_application_path);
1661 _E("unable to unmount the SD application");
1662 err_res = APP2EXT_ERROR_UNMOUNT;
1666 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1667 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1669 _E("close dmcrypt device error(%d)", ret);
1670 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1674 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1676 _E("close dmcrypt device error(%d)", ret);
1677 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1681 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1683 _E("unable to remove loopback setup");
1684 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1687 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1689 _E("unable to remove loopback setup");
1690 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1695 ret = _app2sd_delete_directory(loopback_device);
1697 _E("unable to delete (%s)", loopback_device);
1698 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1702 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1704 _E("unable to rename (%s)", temp_loopback_device);
1705 err_res = APP2EXT_ERROR_MOVE;
1709 ret = _app2sd_delete_directory(temp_application_path);
1711 _E("unable to delete (%s)", temp_application_path);
1712 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1716 return APP2EXT_SUCCESS;
1719 if (old_device_node) {
1720 free(old_device_node);
1721 old_device_node = NULL;
1724 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1725 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1727 _E("close dmcrypt device error(%d)", ret);
1729 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1732 _E("close dmcrypt device error(%d)", ret);
1734 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1736 _E("unable to remove loopback setup");
1738 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1740 _E("unable to remove loopback setup");
1743 _app2sd_delete_loopback_device(temp_loopback_device);
1745 ret = _app2sd_delete_directory(temp_application_path);
1747 _E("unable to delete (%s)", temp_application_path);
1752 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1753 const char *loopback_device, uid_t uid)
1755 int ret = APP2EXT_SUCCESS;
1757 /* unmount the loopback encrypted pseudo device from the application installation path */
1758 ret = _app2sd_unmount_app_content(application_path);
1760 _E("unable to unmount the app content (%d)", ret);
1762 /* detach the loopback encryption setup for the application */
1763 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1764 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1766 _E("close dmcrypt device error (%d)", ret);
1768 ret = _app2sd_remove_all_loopback_encryption_setups(loopback_device);
1770 _E("unable to detach the loopback encryption setup for the application");
1773 /* delete the loopback device from the SD card */
1774 ret = _app2sd_delete_loopback_device(loopback_device);
1776 _E("unable to detach the loopback encryption setup for the application");
1778 /* delete symlink */
1779 _app2sd_delete_symlink(application_path);
1781 /* remove passwrd from DB */
1782 ret = _app2sd_initialize_db();
1784 _E("app2sd db initialize failed");
1786 ret = _app2sd_remove_info_from_db(pkgid, uid);
1788 _E("cannot remove info from db");