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.
28 #include "app2sd_internals.h"
30 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
31 #define DMCRYPT_ITER_TIME 50
32 #define DMCRYPT_KEY_LEN 128
35 static int _app2sd_make_directory(const char *path, uid_t uid)
39 mode_t mode = DIR_PERMS;
41 struct passwd *pwd_result;
42 char buf[1024] = { 0, };
44 ret = _app2sd_delete_directory(path);
46 _E("unable to delete (%s), errno(%d)", path, errno);
47 return APP2EXT_ERROR_DELETE_DIRECTORY;
50 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
51 if (ret != 0 || pwd_result == NULL) {
52 _E("get uid failed(%d)", ret);
53 return APP2EXT_ERROR_ACCESS_FILE;
55 _D("uid(%d), gid(%d)", uid, pwd.pw_gid);
57 /* create directory */
58 ret = mkdir(path, mode);
60 if (errno != EEXIST) {
61 _E("create directory failed," \
62 " error no is (%d)", errno);
63 return APP2EXT_ERROR_CREATE_DIRECTORY;
67 fd = open(path, O_RDONLY|O_DIRECTORY);
69 _E("can't open path(%s)", path);
70 return APP2EXT_ERROR_OPEN_DIR;
73 ret = fchmod(fd, 0755);
75 _E("change file permission error");
77 return APP2EXT_ERROR_ACCESS_FILE;
80 ret = fchown(fd, uid, pwd.pw_gid);
82 _E("change file owner error");
84 return APP2EXT_ERROR_ACCESS_FILE;
89 return APP2EXT_SUCCESS;
92 char *_app2sd_find_associated_device_node(const char *loopback_device)
94 char *ret_result = NULL;
97 char dev[FILENAME_MAX] = { 0, };
100 result = (char *)_app2sd_find_associated_device(loopback_device);
101 if (result == NULL) {
102 _D("there is no the associated file (%s)", loopback_device);
106 /* process the string*/
107 snprintf(dev, FILENAME_MAX - 1, "%s", result);
109 if (strstr(dev, "dev") == NULL) {
110 _E("unable to find the associated file");
114 char *saveptr = NULL;
115 ret_result = strtok_r(dev, delims, &saveptr);
117 devnode = strdup(ret_result);
125 char *_app2sd_create_loopdevice_node(void)
127 char *ret_result = NULL;
128 mode_t mode = DIR_PERMS;
130 int ret = APP2EXT_SUCCESS;
134 result = (char *)_app2sd_find_free_device();
135 _D("find_free_device(%s)", result);
137 /* validate the result */
138 if (result == NULL || strstr(result, "/dev") == NULL) {
139 _D("no device found, creating device node");
146 char dev_path[BUF_SIZE] = { 0, };
147 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
148 while ((fp = fopen(dev_path, "r+")) != NULL) {
150 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
151 _D("next dev path for checking is (%s)",
155 _D("device node candidate is (%s)", dev_path);
157 dev_node = makedev(DEV_MAJOR, count);
158 ret = mknod(dev_path, S_IFBLK | mode, dev_node);
160 _E("error while creating the device node: errno is (%d)",
164 ret_result = (char *)malloc(strlen(dev_path) + 1);
165 if (ret_result == NULL) {
166 _E("unable to allocate memory");
169 memset(ret_result, '\0', strlen(dev_path) + 1);
170 memcpy(ret_result, dev_path, strlen(dev_path));
172 ret_result = (char *)malloc(strlen(result) + 1);
173 if (ret_result == NULL) {
179 memset(ret_result, '\0', strlen(result) + 1);
180 if (strlen(result) > 0)
181 memcpy(ret_result, result, strlen(result) - 1);
190 char *_app2sd_do_loopback_encryption_setup(const char *pkgid,
191 const char *loopback_device, uid_t uid)
193 int ret = APP2EXT_SUCCESS;
196 char *device_node = NULL;
199 _E("invalid argument");
203 /* get password for loopback encryption */
204 ret = _app2sd_initialize_db();
206 _E("app2sd db initialize failed");
210 if ((passwd = _app2sd_get_password_from_db(pkgid, uid)) == NULL) {
211 passwd = (char *)_app2sd_generate_password(pkgid);
212 if (NULL == passwd) {
213 _E("unable to generate password");
216 if ((ret = _app2sd_set_info_in_db(pkgid,
217 passwd, loopback_device, uid)) < 0) {
218 _E("unable to save info");
226 /* get free device node*/
227 device_node = _app2sd_create_loopdevice_node();
228 if (NULL == device_node) {
231 _E("unable to find free loopback node");
235 _D("device_node (%s)", device_node);
237 result = (char *)_app2sd_encrypt_device(device_node,
238 loopback_device, passwd);
239 if (result == NULL) {
240 _E("encryption failed");
245 _D("result (%s)", result);
254 char *_app2sd_do_loopback_duplicate_encryption_setup(const char *pkgid,
255 const char *temp_pkgid, const char *temp_loopback_device,
256 char *passwd, uid_t uid)
259 char *device_node = NULL;
261 if (pkgid == NULL || temp_pkgid == NULL ||
262 temp_loopback_device == NULL || passwd == NULL) {
263 _E("invalid argument");
267 /* get free device node*/
268 device_node = _app2sd_create_loopdevice_node();
269 if (NULL == device_node) {
270 _E("unable to find free loopback node");
273 result = (char *)_app2sd_encrypt_device(device_node,
274 temp_loopback_device, passwd);
275 if (result == NULL) {
276 _E("encryption failed");
279 if (strlen(result) == 0) {
284 _E("error is (%s)", result);
294 int _app2sd_remove_loopback_encryption_setup(const char *loopback_device)
296 int ret = APP2EXT_SUCCESS;
298 char *dev_node = NULL;
300 if ((dev_node = _app2sd_find_associated_device_node(loopback_device))
302 _E("Unable to find the association");
303 ret = APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE;
306 result = (char *)_app2sd_detach_loop_device(dev_node);
307 if (result == NULL) {
308 _E("error in detaching");
309 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
323 int _app2sd_remove_all_loopback_encryption_setups(const char *loopback_device)
325 int ret = APP2EXT_SUCCESS;
327 char *dev_node = NULL;
330 _app2sd_find_associated_device_node(loopback_device))
332 _E("finish to find the association");
333 ret = APP2EXT_SUCCESS;
337 _D("find node (%s)", dev_node);
339 result = (char *)_app2sd_detach_loop_device(dev_node);
340 if (result == NULL) {
341 _E("error in detaching");
342 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
357 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
358 int _app2sd_dmcrypt_setup_device(const char *pkgid,
359 const char *loopback_device, bool is_dup, uid_t uid)
361 int ret = APP2EXT_SUCCESS;
363 char dmcrypt_setup_cmd[BUF_SIZE] = { 0, };
364 char err_buf[BUF_SIZE] = { 0, };
366 if (pkgid == NULL || loopback_device == NULL) {
367 _E("invalid argument");
368 return APP2EXT_ERROR_INVALID_ARGUMENTS;
371 /* get password for dmcrypt encryption */
372 ret = _app2sd_initialize_db();
374 _E("app2sd db initialize failed");
375 return APP2EXT_ERROR_DB_INITIALIZE;
378 passwd = _app2sd_get_password_from_db(pkgid, uid);
379 if (passwd == NULL) {
381 _E("no password found for (%s)", pkgid);
382 return APP2EXT_ERROR_SQLITE_REGISTRY;
384 passwd = (char *)_app2sd_generate_password(pkgid);
385 if (NULL == passwd) {
386 _E("unable to generate password\n");
387 return APP2EXT_ERROR_PASSWD_GENERATION;
389 if ((ret = _app2sd_set_info_in_db(pkgid, passwd,
390 loopback_device, uid)) < 0) {
391 _E("unable to save password");
394 return APP2EXT_ERROR_SQLITE_REGISTRY;
399 snprintf(dmcrypt_setup_cmd, BUF_SIZE, "/bin/echo '%s' | /sbin/cryptsetup -q -i %d " \
400 "-c aes-cbc-lmk -s %d --align-payload=8 luksFormat %s",
401 passwd, DMCRYPT_ITER_TIME, DMCRYPT_KEY_LEN, loopback_device);
403 ret = system(dmcrypt_setup_cmd);
405 strerror_r(errno, err_buf, sizeof(err_buf));
406 _E("Error setting up dmcrypt on app2sd file, " \
407 "error(%s), ret(%d)", err_buf, ret);
412 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
423 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
424 bool is_dup, uid_t uid, char **dev_node)
426 int ret = APP2EXT_SUCCESS;
428 char dmcrypt_open_cmd[BUF_SIZE] = { 0, };
429 char dev_name[BUF_SIZE] = { 0, };
430 char buf[BUF_SIZE] = { 0, };
433 if (pkgid == NULL || loopback_device == NULL) {
434 _E("invalid argument");
435 return APP2EXT_ERROR_INVALID_ARGUMENTS;
439 snprintf(dev_name, BUF_SIZE, "%s.new_%d", pkgid, uid);
441 snprintf(dev_name, BUF_SIZE, "%s_%d", pkgid, uid);
443 /* get password for dmcrypt encryption */
444 ret = _app2sd_initialize_db();
446 _E("app2sd db initialize failed");
447 return APP2EXT_ERROR_DB_INITIALIZE;
450 passwd = _app2sd_get_password_from_db(pkgid, uid);
451 if (passwd == NULL) {
452 _E("no password found for [%s]", pkgid);
453 return APP2EXT_ERROR_SQLITE_REGISTRY;
456 if (_app2sd_check_is_luks_device(loopback_device) == 0) {
457 _W("legacy image format!");
458 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
459 "/bin/echo '%s' | /sbin/cryptsetup " \
460 "-M plain -c aes-cbc-plain -h plain open %s %s",
461 passwd, loopback_device, dev_name);
463 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
464 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen %s %s",
465 passwd, loopback_device, dev_name);
469 ret = system(dmcrypt_open_cmd);
471 strerror_r(errno, buf, sizeof(buf));
472 _E("error opening dmcrypt device, error: [%s]", buf);
473 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
476 snprintf(buf, BUF_SIZE, "/dev/mapper/%s", dev_name);
478 *dev_node = (char *)calloc(len + 1, sizeof(char));
479 if (*dev_node == NULL) {
480 _E("memory alloc failed");
481 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
483 snprintf(*dev_node, len + 1, "%s", buf);
488 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
490 int ret = APP2EXT_SUCCESS;
491 char dev_node[BUF_SIZE] = { '\0' };
492 char dmcrypt_close_cmd[BUF_SIZE] = { '\0' };
493 char err_buf[BUF_SIZE] = { '\0' };
494 char *t_dev_node = NULL;
497 _E("invalid argument\n");
498 return APP2EXT_ERROR_INVALID_ARGUMENTS;
501 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
503 _W("no associated device node(%s_%d) found", pkgid, uid);
504 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
510 snprintf(dev_node, BUF_SIZE, "/dev/mapper/%s_%d", pkgid, uid);
511 snprintf(dmcrypt_close_cmd, BUF_SIZE, "/sbin/cryptsetup -q luksClose %s", dev_node);
512 ret = system(dmcrypt_close_cmd);
514 strerror_r(errno, err_buf, sizeof(err_buf));
515 _E("error closing dmcrypt on app2sd file,"\
516 " error: [%s]", err_buf);
517 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
523 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
525 char *dev_node = NULL;
526 char buf[BUF_SIZE] = { 0, };
529 snprintf(buf, BUF_SIZE, "/dev/mapper/%s_%d", pkgid, uid);
531 dev_node = (char *)calloc(len + 1, sizeof(char));
532 if (dev_node == NULL) {
533 _E("memory alloc failed");
536 snprintf(dev_node, len + 1, "%s", buf);
538 if (access(dev_node, F_OK) == 0) {
539 _D("device_node: (%s)", dev_node);
542 _D("can not access dev_node(%s), errno(%d)", dev_node, errno);
550 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
551 const char *temp_loopback_device, uid_t uid)
553 int ret = APP2EXT_SUCCESS;
554 char *device_node = NULL;
556 if (pkgid == NULL || temp_loopback_device == NULL) {
557 _E("invalid argument\n");
561 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true, uid);
563 _E("dmcrypt setup device error(%d)", ret);
567 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
570 _E("dmcrypt open device error");
578 int _app2sd_create_loopback_device(const char *pkgid,
579 const char *loopback_device, int size)
581 int ret = APP2EXT_SUCCESS;
582 char command[FILENAME_MAX] = { 0, };
583 char buff[BUF_SIZE] = { 0, };
586 if (NULL == pkgid || size <= 0) {
587 _E("invalid argument");
588 return APP2EXT_ERROR_INVALID_ARGUMENTS;
590 snprintf(command, FILENAME_MAX - 1, "of=%s", loopback_device);
591 snprintf(buff, BUF_SIZE - 1, "count=%d", size);
593 const char *argv1[] = { "/bin/dd", "if=/dev/zero",
594 command, "bs=1M", buff, NULL };
596 if ((fp = fopen(loopback_device, "r+")) != NULL) {
597 _W("encrypted file already exists (%s)",
600 return APP2EXT_ERROR_PKG_EXISTS;
603 ret = _xsystem(argv1);
605 _E("command (%s) failed, ret(%d), errno(%d)", command, ret, errno);
610 int _app2sd_delete_loopback_device(const char *loopback_device)
612 int ret = APP2EXT_SUCCESS;
614 ret = unlink(loopback_device);
616 if (errno == ENOENT) {
617 _W("unable to access file (%s)", loopback_device);
619 _E("unable to delete (%s)", loopback_device);
620 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
624 return APP2EXT_SUCCESS;
627 int _app2sd_create_file_system(const char *device_path)
629 int ret = APP2EXT_SUCCESS;
631 char err_buf[1024] = {0,};
633 if (device_path == NULL) {
635 return APP2EXT_ERROR_INVALID_ARGUMENTS;
638 /* Format the filesystem [create a filesystem]*/
639 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
640 fp = fopen(device_path, "r+");
642 strerror_r(errno, err_buf, sizeof(err_buf));
643 _E("unable to access (%s) error is (%d, %s)",
644 device_path, errno, err_buf);
645 return APP2EXT_ERROR_ACCESS_FILE;
649 ret = _xsystem(argv);
651 strerror_r(errno, err_buf, sizeof(err_buf));
652 _E("creating file system failed, error is (%s)",
654 return APP2EXT_ERROR_CREATE_FS;
659 static int _app2sd_create_dir_with_link(const char *application_path,
660 const char *pkgid, const char *dir_name, uid_t uid)
662 int ret = APP2EXT_SUCCESS;
663 char application_dir_mmc_path[FILENAME_MAX] = { 0, };
664 char application_dir_path[FILENAME_MAX] = { 0, };
666 snprintf(application_dir_mmc_path, FILENAME_MAX - 1, "%s/.mmc/%s",
667 application_path, dir_name);
668 snprintf(application_dir_path, FILENAME_MAX, "%s/%s",
669 application_path, dir_name);
671 ret = _app2sd_make_directory(application_dir_mmc_path, uid);
673 _E("create directory failed");
674 return APP2EXT_ERROR_CREATE_DIRECTORY;
677 if ((ret = symlink(application_dir_mmc_path,
678 application_dir_path)) < 0) {
679 if (errno == EEXIST) {
680 _D("file with symlink name present (%s)",
681 application_dir_path);
683 _E("symbolic link creation "
684 "failed, error no is (%d)", errno);
685 return APP2EXT_ERROR_CREATE_SYMLINK;
689 return APP2EXT_SUCCESS;
692 static int _app2sd_create_directory_entry(const char *application_path,
693 const char *pkgid, GList *dir_list, uid_t uid)
695 int ret = APP2EXT_SUCCESS;
697 app2ext_dir_details *dir_detail = NULL;
699 list = g_list_first(dir_list);
701 dir_detail = (app2ext_dir_details *)list->data;
702 if (dir_detail && dir_detail->name
703 && dir_detail->type == APP2EXT_DIR_RO) {
704 ret = _app2sd_create_dir_with_link(application_path,
705 pkgid, dir_detail->name, uid);
709 list = g_list_next(list);
711 return APP2EXT_SUCCESS;
714 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
715 const char *dev, int mount_type, GList *dir_list,
716 app2sd_cmd cmd, uid_t uid)
718 int ret = APP2EXT_SUCCESS;
720 char application_mmc_path[FILENAME_MAX] = { 0, };
721 char temp_path[FILENAME_MAX] = { 0, };
722 char err_buf[1024] = {0,};
723 struct timespec time = {
725 .tv_nsec = 1000 * 1000 * 200
729 _E("input param is NULL (%s)",
731 return APP2EXT_ERROR_INVALID_ARGUMENTS;
734 /* check directory existence */
735 fd = open(application_path, O_RDONLY|O_DIRECTORY);
737 _E("path(%s) error(%d)", application_path, errno);
738 return APP2EXT_ERROR_OPEN_DIR;
742 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
744 fd = open(application_mmc_path, O_RDONLY|O_DIRECTORY);
746 _E("path(%s) error(%d)", application_mmc_path, errno);
747 return APP2EXT_ERROR_OPEN_DIR;
751 nanosleep(&time, NULL); /* 200ms sleep */
752 _D("give a delay for mount");
754 switch (mount_type) {
756 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
757 MS_MGC_VAL | MS_RDONLY | MS_NOSUID, NULL)) < 0) {
758 _E("read only mount failed, " \
760 "dev is (%s) path is (%s)",
761 errno, dev, application_mmc_path);
762 ret = APP2EXT_ERROR_MOUNT;
766 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
767 MS_MGC_VAL | MS_NOSUID, NULL)) < 0) {
768 _E("read write mount failed, " \
769 "errono is (%d)", errno);
770 ret = APP2EXT_ERROR_MOUNT;
773 case MOUNT_TYPE_RW_NOEXEC:
774 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
775 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID, NULL)) < 0) {
776 _E("rwnx mount failed " \
777 "errono is (%d)", errno);
778 ret = APP2EXT_ERROR_MOUNT;
781 case MOUNT_TYPE_RD_REMOUNT:
782 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
783 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT | MS_NOSUID,
785 _E("read remount failed "
786 "errono is (%d)", errno);
787 ret = APP2EXT_ERROR_MOUNT;
790 case MOUNT_TYPE_RW_REMOUNT:
791 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
792 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID, NULL)) < 0) {
793 _E("read write remount failed "
794 "errono(%d), errstr(%s)", errno,
795 strerror_r(errno, err_buf, sizeof(err_buf)));
796 ret = APP2EXT_ERROR_MOUNT;
800 _E("invalid mount type");
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);
810 if (mount_type != MOUNT_TYPE_RD &&
811 mount_type != MOUNT_TYPE_RD_REMOUNT) {
812 /* change lost+found permission */
813 snprintf(temp_path, FILENAME_MAX - 1, "%s/lost+found",
814 application_mmc_path);
815 ret = _app2sd_make_directory(temp_path, uid);
817 _E("create directory(%s) failed", temp_path);
818 return APP2EXT_ERROR_CREATE_DIRECTORY;
825 int _app2sd_unmount_app_content(const char *application_path)
827 int ret = APP2EXT_SUCCESS;
828 char application_dir_mmc_path[FILENAME_MAX] = { 0, };
829 char err_buf[1024] = {0,};
831 snprintf(application_dir_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
833 if ((ret = umount(application_dir_mmc_path)) < 0) {
834 strerror_r(errno, err_buf, sizeof(err_buf));
835 _D("unable to umount the dir, ret(%d) error(%d, %s)",
836 ret, errno, err_buf);
842 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
844 int ret = APP2EXT_SUCCESS;
846 ret = _app2sd_copy_dir(src_path, arch_path);
847 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
848 char err_buf[1024] = {0,};
849 strerror_r(errno, err_buf, sizeof(err_buf));
850 _E("unable to copy from (%s) to (%s), err is (%s)",
851 src_path, arch_path, err_buf);
852 return APP2EXT_ERROR_MOVE;
855 ret = _app2sd_delete_directory((char *)src_path);
857 _E("unable to delete (%s)", src_path);
858 return APP2EXT_ERROR_DELETE_DIRECTORY;
864 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
865 uid_t uid, char *mmc_path, char **image_path)
867 int ret = APP2EXT_SUCCESS;
868 mode_t mode = DIR_PERMS;
869 char temp_dir_path[FILENAME_MAX] = { 0, };
870 char application_mmc_path[FILENAME_MAX] = { 0, };
871 char application_archive_path[FILENAME_MAX] = { 0, };
872 char application_path[FILENAME_MAX] = { 0, };
873 char loopback_device[FILENAME_MAX] = { 0, };
874 unsigned long long total_size = 0;
876 int reqd_disk_size = 0;
877 char *device_node = NULL;
878 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
881 int free_mmc_mem = 0;
884 app2ext_dir_details *dir_detail = NULL;
885 char err_buf[1024] = { 0,};
886 char *encoded_id = NULL;
888 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
889 if (encoded_id == NULL)
890 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
892 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
893 mmc_path, EXTIMG_DIR, encoded_id);
895 if (_is_global(uid)) {
896 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
897 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
899 tzplatform_set_user(uid);
900 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
901 tzplatform_getenv(TZ_USER_APP), pkgid);
902 tzplatform_reset_user();
905 /* check whether application is in external memory or not */
906 fp = fopen(loopback_device, "r+");
908 _W("Already %s entry is present in the SD Card, " \
909 "delete entry and go on without return", pkgid);
911 _app2sd_force_clean(pkgid, application_path, loopback_device, uid);
914 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
916 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
919 ret = mkdir(application_mmc_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 ret = mkdir(application_archive_path, mode);
930 if (errno != EEXIST) {
931 _E("unable to create directory for archiving," \
932 " error(%d)", errno);
933 return APP2EXT_ERROR_CREATE_DIRECTORY;
937 list = g_list_first(dir_list);
939 dir_detail = (app2ext_dir_details *)list->data;
940 if (dir_detail && dir_detail->name
941 && dir_detail->type == APP2EXT_DIR_RO) {
942 memset(temp_dir_path, '\0', FILENAME_MAX);
943 snprintf(temp_dir_path, FILENAME_MAX,
944 "%s/%s", application_path,
946 _D("cal size of app dirs, temp_dir_path(%s)",
949 _app2sd_calculate_dir_size(temp_dir_path);
951 list = g_list_next(list);
954 reqd_size = ((total_size) / (1024 * 1024)) + 2;
955 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
957 /* find avialable free memory in the MMC card */
958 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
960 _E("unable to get available free memory in MMC (%d)", ret);
961 return APP2EXT_ERROR_MMC_STATUS;
963 /* if avaialalbe free memory in MMC is less than
964 * required size + 5MB, return error
966 if (reqd_disk_size > free_mmc_mem) {
967 _E("insufficient memory in MMC for application installation (%d)",
969 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
971 /* create a loopback device */
972 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
973 (reqd_disk_size + PKG_BUF_SIZE));
975 _E("loopback node creation failed");
979 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
980 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
982 _E("dmcrypt setup device error(%d)", ret);
983 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
986 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
989 _E("dmcrypt open device error");
990 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
993 /* perform loopback encryption setup */
994 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
995 loopback_device, uid);
997 _E("loopback encryption setup failed");
998 return APP2EXT_ERROR_DO_LOSETUP;
1000 _D("device_node (%s)", device_node);
1001 /* check whether loopback device is associated with device node or not */
1002 devi = _app2sd_find_associated_device_node(loopback_device);
1004 _E("finding associated device node failed");
1005 ret = APP2EXT_ERROR_DO_LOSETUP;
1012 /* format the loopback file system */
1013 ret = _app2sd_create_file_system(device_node);
1015 _E("create ext4 filesystem failed");
1016 ret = APP2EXT_ERROR_CREATE_FS;
1020 list = g_list_first(dir_list);
1022 dir_detail = (app2ext_dir_details *)list->data;
1023 if (dir_detail && dir_detail->name
1024 && dir_detail->type == APP2EXT_DIR_RO) {
1025 memset(temp_dir_path, '\0', FILENAME_MAX);
1026 snprintf(temp_dir_path, FILENAME_MAX,
1027 "%s/%s", application_path,
1029 _D("app2archive, temp_dir_path(%s)",
1031 ret = _app2sd_move_to_archive(temp_dir_path,
1032 application_archive_path);
1034 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1035 _E("unable to access (%s)",
1038 _E("unable to copy from (%s) to (%s)",
1040 application_archive_path);
1045 list = g_list_next(list);
1048 /* mount the loopback encrypted pseudo device on application installation path
1049 * as with Read Write permission
1051 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
1052 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
1058 list = g_list_first(dir_list);
1060 dir_detail = (app2ext_dir_details *)list->data;
1061 if (dir_detail && dir_detail->name
1062 && dir_detail->type == APP2EXT_DIR_RO) {
1063 memset(temp_dir_path, '\0', FILENAME_MAX);
1064 snprintf(temp_dir_path, FILENAME_MAX,
1065 "%s/%s", application_archive_path,
1067 _D("archive2mmc, temp_dir_path(%s)",
1069 ret = _app2sd_copy_dir(temp_dir_path,
1070 application_mmc_path);
1072 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1073 _E("unable to access (%s)",
1077 err_buf, sizeof(err_buf));
1078 _E("unable to copy from (%s) to (%s)," \
1081 application_mmc_path, err_buf);
1085 ret = _app2sd_delete_directory(temp_dir_path);
1087 _E("unable to delete (%s)", temp_dir_path);
1091 list = g_list_next(list);
1094 ret = _app2sd_delete_directory(application_archive_path);
1096 _E("unable to delete (%s)", application_archive_path);
1097 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
1101 *image_path = strdup(loopback_device);
1102 return APP2EXT_SUCCESS;
1114 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
1115 uid_t uid, char *mmc_path)
1117 int ret = APP2EXT_SUCCESS;
1118 mode_t mode = DIR_PERMS;
1119 char temp_dir_path[FILENAME_MAX] = { 0, };
1120 char application_mmc_path[FILENAME_MAX] = { 0, };
1121 char application_archive_path[FILENAME_MAX] = { 0, };
1122 char application_path[FILENAME_MAX] = { 0, };
1123 char loopback_device[FILENAME_MAX] = { 0, };
1124 char *device_node = NULL;
1127 app2ext_dir_details *dir_detail = NULL;
1129 int free_internal_mem = 0;
1130 struct statvfs buf = {0,};
1131 unsigned long long temp = 0;
1132 char err_buf[1024] = {0,};
1133 char *encoded_id = NULL;
1135 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1136 if (encoded_id == NULL)
1137 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1139 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1140 mmc_path, EXTIMG_DIR, encoded_id);
1142 if (_is_global(uid)) {
1143 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1144 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1146 tzplatform_set_user(uid);
1147 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1148 tzplatform_getenv(TZ_USER_APP), pkgid);
1149 tzplatform_reset_user();
1152 /* check whether application is in external memory or not */
1153 fp = fopen(loopback_device, "r+");
1155 _E("application (%s) is not installed on SD Card",
1157 return APP2EXT_ERROR_FILE_ABSENT;
1163 memset((void *)&buf, '\0', sizeof(struct statvfs));
1164 ret = statvfs(INTERNAL_STORAGE_PATH, &buf);
1166 temp = (buf.f_bsize * buf.f_bavail) / (1024 * 1024);
1167 free_internal_mem = (int)temp;
1169 _E("unable to get internal storage size");
1170 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1173 fp = fopen(loopback_device, "r+");
1175 _E("app entry is not present in SD card");
1176 return APP2EXT_ERROR_INVALID_PACKAGE;
1180 /* get installed app size*/
1181 temp = _app2sd_calculate_file_size(loopback_device);
1182 reqd_size = (int)((temp) / (1024 * 1024));
1183 _D("reqd size is (%d)", reqd_size);
1185 if (reqd_size == 0) {
1186 _E("app entry is not present in SD Card");
1187 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1190 _D("reqd size: (%d)MB, free internal mem: (%d)MB",
1191 reqd_size, free_internal_mem);
1193 /* if avaialalbe free memory in internal storage is
1194 * less than required size, return error
1196 if (reqd_size > free_internal_mem) {
1197 _E("innsufficient memory in internal storage" \
1198 " for application installation (%d)", ret);
1199 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1202 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1204 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1206 device_node = _app2sd_find_associated_device_node(loopback_device);
1208 if (NULL == device_node) {
1209 /* do loopback setup */
1210 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1211 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1212 false, uid, &device_node);
1214 _E("dmcrypt open device error(%d)", ret);
1215 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1218 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1219 loopback_device, uid);
1220 if (device_node == NULL) {
1221 _E("loopback encryption setup failed");
1222 return APP2EXT_ERROR_DO_LOSETUP;
1226 ret = _app2sd_mount_app_content(application_path,
1227 pkgid, device_node, MOUNT_TYPE_RW,
1228 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1231 ret = APP2EXT_ERROR_MOUNT_PATH;
1235 /* do re-mounting */
1236 ret = _app2sd_mount_app_content(application_path,
1237 pkgid, device_node, MOUNT_TYPE_RW_REMOUNT,
1238 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1240 _E("re-mount failed");
1241 ret = APP2EXT_ERROR_MOUNT_PATH;
1246 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
1248 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
1251 ret = mkdir(application_archive_path, mode);
1253 if (errno != EEXIST) {
1254 _E("unable to create directory for archiving," \
1255 " error(%d)", errno);
1256 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
1261 list = g_list_first(dir_list);
1263 dir_detail = (app2ext_dir_details *)list->data;
1264 if (dir_detail && dir_detail->name
1265 && dir_detail->type == APP2EXT_DIR_RO) {
1266 /* archiving code */
1267 memset(temp_dir_path, '\0', FILENAME_MAX);
1268 snprintf(temp_dir_path, FILENAME_MAX,
1269 "%s/%s", application_mmc_path,
1271 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1272 ret = _app2sd_copy_dir(temp_dir_path,
1273 application_archive_path);
1275 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1276 _E("unable to access (%s)",
1280 err_buf, sizeof(err_buf));
1281 _E("unable to copy from (%s) to (%s),"
1284 application_archive_path, err_buf);
1289 /* delete the symbolic link files [bin, lib, res]*/
1290 memset(temp_dir_path, '\0', FILENAME_MAX);
1291 snprintf(temp_dir_path, FILENAME_MAX,
1292 "%s/%s", application_path,
1294 _D("unlink, temp_dir_path(%s)", temp_dir_path);
1295 ret = unlink(temp_dir_path);
1297 if (errno == ENOENT) {
1298 _W("directory (%s) does not exist",
1301 _E("unable to remove the symbolic link file (%s)," \
1302 " it is already unlinked",
1308 /* Copy content to destination */
1309 memset(temp_dir_path, '\0', FILENAME_MAX);
1310 snprintf(temp_dir_path, FILENAME_MAX,
1311 "%s/%s", application_archive_path,
1313 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1314 ret = _app2sd_copy_dir(temp_dir_path, application_path);
1316 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1317 _E("unable to access (%s)",
1321 err_buf, sizeof(err_buf));
1322 _E("unable to copy from (%s) to (%s) " \
1325 application_path, err_buf);
1330 list = g_list_next(list);
1333 _D("copying file completed");
1334 ret = _app2sd_unmount_app_content(application_path);
1336 _E("unable to unmount SD directory for app (%s)",
1339 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1340 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1342 _E("close dmcrypt device error(%d)", ret);
1344 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1346 _E("unable to detach loopback setup for (%s)",
1350 ret = _app2sd_delete_loopback_device(loopback_device);
1352 _E("unable to delete the loopback device for (%s)",
1355 ret = _app2sd_delete_directory(application_mmc_path);
1357 _E("unable to delete (%s)", application_mmc_path);
1359 ret = _app2sd_delete_directory(application_archive_path);
1361 _E("unable to delete (%s)", application_archive_path);
1363 /* remove passwrd from DB */
1364 ret = _app2sd_initialize_db();
1366 _E("app2sd db initialize failed");
1368 ret = _app2sd_remove_info_from_db(pkgid, uid);
1370 _E("cannot remove info from db");
1372 return APP2EXT_SUCCESS;
1383 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1384 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
1386 int ret = APP2EXT_SUCCESS;
1388 switch (move_type) {
1389 case APP2EXT_MOVE_TO_EXT:
1390 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1391 uid, mmc_path, image_path);
1393 _E("move app to external memory failed(%d)", ret);
1397 case APP2EXT_MOVE_TO_PHONE:
1398 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1401 _E("move app to internal memory failed(%d)", ret);
1406 _E("invalid argument");
1407 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1413 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1415 char path[FILENAME_MAX] = { 0, };
1416 int ret = APP2EXT_SUCCESS;
1418 app2ext_dir_details *dir_detail = NULL;
1420 list = g_list_first(dir_list);
1422 dir_detail = (app2ext_dir_details *)list->data;
1423 if (dir_detail && dir_detail->name
1424 && dir_detail->type == APP2EXT_DIR_RO) {
1425 memset((void *)&path, '\0', FILENAME_MAX);
1426 snprintf(path, FILENAME_MAX - 1, "%s/%s", src,
1428 ret = _app2sd_copy_dir(path, dest);
1430 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1431 _E("unable to access (%s)", path);
1433 _E("unable to copy from (%s) " \
1434 "to (%s), errno is (%d)",
1436 return APP2EXT_ERROR_MOVE;
1440 list = g_list_next(list);
1443 return APP2EXT_SUCCESS;
1446 int _app2sd_duplicate_device(const char *pkgid,
1447 const char *loopback_device,
1448 const char *temp_pkgid,
1449 const char *temp_application_path,
1450 const char *temp_loopback_device,
1451 GList *dir_list, char *dev_node, int size,
1456 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1458 char *result = NULL;
1459 char *passwd = NULL;
1462 /* create a new loopback device */
1463 ret = _app2sd_create_loopback_device(temp_pkgid,
1464 temp_loopback_device, (size + PKG_BUF_SIZE));
1466 _E("package already present");
1470 /* perform loopback encryption setup */
1471 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1472 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1473 temp_loopback_device, uid);
1475 _E("dmcrypt duplicate encryption setup failed");
1476 _app2sd_delete_loopback_device(temp_loopback_device);
1477 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1480 /* get password for loopback encryption */
1481 ret = _app2sd_initialize_db();
1483 _E("app2sd db initialize failed");
1484 return APP2EXT_ERROR_DB_INITIALIZE;
1487 if ((passwd = _app2sd_get_password_from_db(pkgid, uid)) == NULL) {
1488 passwd = (char *)_app2sd_generate_password(pkgid);
1489 if (NULL == passwd) {
1490 _E("unable to generate password");
1491 return APP2EXT_ERROR_PASSWD_GENERATION;
1493 if ((ret = _app2sd_set_info_in_db(pkgid,
1494 passwd, loopback_device, uid)) < 0) {
1495 _E("unable to save info");
1498 return APP2EXT_ERROR_SQLITE_REGISTRY;
1503 dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1504 temp_pkgid, temp_loopback_device, passwd, uid);
1506 _E("losetup failed, device node is (%s)", dev_node);
1507 _app2sd_delete_loopback_device(temp_loopback_device);
1510 return APP2EXT_ERROR_DO_LOSETUP;
1514 _D("duplicate setup SUCCESS");
1516 /* check whether loopback device is associated with
1517 * device node or not
1519 devi = _app2sd_find_associated_device_node(temp_loopback_device);
1521 _E("finding associated device node failed");
1522 err_res = APP2EXT_ERROR_DO_LOSETUP;
1525 _D("losetup SUCCESS");
1528 /* format the loopback file system */
1529 ret = _app2sd_create_file_system(dev_node);
1531 _E("creating fs failed");
1532 err_res = APP2EXT_ERROR_CREATE_FS;
1535 _D("create filesystem SUCCESS");
1537 /* do mounting for new dev*/
1538 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1539 dev_node, MOUNT_TYPE_RW, dir_list,
1540 APP2SD_PRE_UPGRADE, uid);
1542 _E("remount failed");
1543 err_res = APP2EXT_ERROR_MOUNT_PATH;
1547 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1554 return APP2EXT_SUCCESS;
1558 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1559 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1561 _E("close dmcrypt device error(%d)", ret);
1563 result = _app2sd_detach_loop_device(dev_node);
1569 _app2sd_delete_loopback_device(temp_loopback_device);
1577 int _app2sd_update_loopback_device_size(const char *pkgid,
1578 const char *loopback_device,
1579 const char *application_path,
1580 const char *temp_pkgid,
1581 const char *temp_loopback_device,
1582 const char *temp_application_path,
1583 int size, GList *dir_list,
1587 char *device_node = NULL;
1588 char *old_device_node = NULL;
1590 char application_mmc_path[FILENAME_MAX] = { 0, };
1591 char temp_application_mmc_path[FILENAME_MAX] = { 0, };
1593 ret = _app2sd_duplicate_device(pkgid, loopback_device,
1594 temp_pkgid, temp_application_path, temp_loopback_device,
1595 dir_list, device_node, size, uid);
1597 _E("creating duplicate device failed");
1601 /* get the associated device node for SD card applicatione */
1602 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1604 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1606 old_device_node = _app2sd_find_associated_device_node(loopback_device);
1608 if (NULL == old_device_node) {
1609 /* do loopback setup */
1610 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1611 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1612 false, uid, &old_device_node);
1614 _E("dmcrypt open device error");
1615 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1619 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1620 loopback_device, uid);
1621 if (old_device_node == NULL) {
1622 _E("loopback encryption setup failed");
1623 err_res = APP2EXT_ERROR_DO_LOSETUP;
1628 ret = _app2sd_mount_app_content(application_path, pkgid,
1629 old_device_node, MOUNT_TYPE_RW, dir_list,
1630 APP2SD_PRE_UPGRADE, uid);
1632 _E("remount failed");
1633 err_res = APP2EXT_ERROR_MOUNT_PATH;
1636 /* do re-mounting */
1637 ret = _app2sd_mount_app_content(application_path, pkgid,
1638 old_device_node, MOUNT_TYPE_RW_REMOUNT, dir_list,
1639 APP2SD_PRE_UPGRADE, uid);
1641 _E("remount failed");
1642 err_res = APP2EXT_ERROR_MOUNT_PATH;
1646 snprintf(application_mmc_path, FILENAME_MAX - 1,
1647 "%s/.mmc", application_path);
1648 snprintf(temp_application_mmc_path, FILENAME_MAX - 1,
1649 "%s/.mmc", temp_application_path);
1651 ret = _app2sd_copy_ro_content(application_mmc_path,
1652 temp_application_mmc_path, dir_list);
1654 _E("copy ro content failed");
1658 ret = _app2sd_unmount_app_content(application_path);
1660 _E("unable to unmount the SD application");
1661 err_res = APP2EXT_ERROR_UNMOUNT;
1664 ret = _app2sd_unmount_app_content(temp_application_path);
1666 _E("unable to unmount the SD application");
1667 err_res = APP2EXT_ERROR_UNMOUNT;
1671 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1672 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1674 _E("close dmcrypt device error(%d)", ret);
1675 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1679 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1681 _E("close dmcrypt device error(%d)", ret);
1682 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1686 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1688 _E("unable to remove loopback setup");
1689 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1692 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1694 _E("unable to remove loopback setup");
1695 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1700 ret = _app2sd_delete_directory(loopback_device);
1702 _E("unable to delete (%s)", loopback_device);
1703 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1707 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1709 _E("unable to rename (%s)", temp_loopback_device);
1710 err_res = APP2EXT_ERROR_MOVE;
1714 ret = _app2sd_delete_directory(temp_application_path);
1716 _E("unable to delete (%s)", temp_application_path);
1717 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1721 return APP2EXT_SUCCESS;
1724 if (old_device_node) {
1725 free(old_device_node);
1726 old_device_node = NULL;
1729 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1730 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1732 _E("close dmcrypt device error(%d)", ret);
1734 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1737 _E("close dmcrypt device error(%d)", ret);
1739 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1741 _E("unable to remove loopback setup");
1743 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1745 _E("unable to remove loopback setup");
1748 _app2sd_delete_loopback_device(temp_loopback_device);
1750 ret = _app2sd_delete_directory(temp_application_path);
1752 _E("unable to delete (%s)", temp_application_path);
1757 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1758 const char *loopback_device, uid_t uid)
1760 int ret = APP2EXT_SUCCESS;
1762 /* unmount the loopback encrypted pseudo device from the application installation path */
1763 ret = _app2sd_unmount_app_content(application_path);
1765 _W("unable to unmount the app content (%d)", ret);
1767 /* detach the loopback encryption setup for the application */
1768 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1769 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1771 _W("close dmcrypt device error (%d)", ret);
1773 ret = _app2sd_remove_all_loopback_encryption_setups(loopback_device);
1775 _W("unable to detach the loopback encryption setup for the application");
1778 /* delete the loopback device from the SD card */
1779 ret = _app2sd_delete_loopback_device(loopback_device);
1781 _W("unable to detach the loopback encryption setup for the application");
1783 /* delete symlink */
1784 _app2sd_delete_symlink(application_path);
1786 /* remove passwrd from DB */
1787 ret = _app2sd_initialize_db();
1789 _W("app2sd db initialize failed");
1791 ret = _app2sd_remove_info_from_db(pkgid, uid);
1793 _W("cannot remove info from db");