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, sizeof(dev), "%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, sizeof(dev_path), "/dev/loop%d", count);
148 while ((fp = fopen(dev_path, "r+")) != NULL) {
150 snprintf(dev_path, sizeof(dev_path), "/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();
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();
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, sizeof(dmcrypt_setup_cmd),
400 "/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, sizeof(dev_name), "%s.new_%d", pkgid, uid);
442 snprintf(dev_name, sizeof(dev_name), "%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;
451 passwd = _app2sd_get_password_from_db(pkgid, uid);
452 if (passwd == NULL) {
453 _E("no password found for [%s]", pkgid);
454 return APP2EXT_ERROR_SQLITE_REGISTRY;
457 if (_app2sd_check_is_luks_device(loopback_device) == 0) {
458 _W("legacy image format!");
459 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
460 "/bin/echo '%s' | /sbin/cryptsetup " \
461 "-M plain -c aes-cbc-plain -h plain open %s %s",
462 passwd, loopback_device, dev_name);
464 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
465 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen %s %s",
466 passwd, loopback_device, dev_name);
470 ret = system(dmcrypt_open_cmd);
472 strerror_r(errno, buf, sizeof(buf));
473 _E("error opening dmcrypt device, error: [%s]", buf);
474 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
477 snprintf(buf, sizeof(buf), "/dev/mapper/%s", dev_name);
479 *dev_node = (char *)calloc(len + 1, sizeof(char));
480 if (*dev_node == NULL) {
481 _E("memory alloc failed");
482 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
484 snprintf(*dev_node, len + 1, "%s", buf);
489 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
491 int ret = APP2EXT_SUCCESS;
492 char dev_node[BUF_SIZE] = { '\0' };
493 char dmcrypt_close_cmd[BUF_SIZE] = { '\0' };
494 char err_buf[BUF_SIZE] = { '\0' };
495 char *t_dev_node = NULL;
498 _E("invalid argument\n");
499 return APP2EXT_ERROR_INVALID_ARGUMENTS;
502 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
504 _W("no associated device node(%s_%d) found", pkgid, uid);
505 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
511 snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
512 snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
513 "/sbin/cryptsetup -q luksClose %s", dev_node);
514 ret = system(dmcrypt_close_cmd);
516 strerror_r(errno, err_buf, sizeof(err_buf));
517 _E("error closing dmcrypt on app2sd file,"\
518 " error: [%s]", err_buf);
519 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
525 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
527 char *dev_node = NULL;
528 char buf[BUF_SIZE] = { 0, };
531 snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
533 dev_node = (char *)calloc(len + 1, sizeof(char));
534 if (dev_node == NULL) {
535 _E("memory alloc failed");
538 snprintf(dev_node, len + 1, "%s", buf);
540 if (access(dev_node, F_OK) == 0) {
541 _D("device_node: (%s)", dev_node);
544 _D("can not access dev_node(%s), errno(%d)", dev_node, errno);
552 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
553 const char *temp_loopback_device, uid_t uid)
555 int ret = APP2EXT_SUCCESS;
556 char *device_node = NULL;
558 if (pkgid == NULL || temp_loopback_device == NULL) {
559 _E("invalid argument\n");
563 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true, uid);
565 _E("dmcrypt setup device error(%d)", ret);
569 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
572 _E("dmcrypt open device error");
580 int _app2sd_create_loopback_device(const char *pkgid,
581 const char *loopback_device, int size)
583 int ret = APP2EXT_SUCCESS;
584 char command[FILENAME_MAX] = { 0, };
585 char buff[BUF_SIZE] = { 0, };
588 if (NULL == pkgid || size <= 0) {
589 _E("invalid argument");
590 return APP2EXT_ERROR_INVALID_ARGUMENTS;
592 snprintf(command, sizeof(command), "of=%s", loopback_device);
593 snprintf(buff, sizeof(buff), "count=%d", size);
595 const char *argv1[] = { "/bin/dd", "if=/dev/zero",
596 command, "bs=1M", buff, NULL };
598 if ((fp = fopen(loopback_device, "r+")) != NULL) {
599 _W("encrypted file already exists (%s)",
602 return APP2EXT_ERROR_PKG_EXISTS;
605 ret = _xsystem(argv1);
607 _E("command (%s) failed, ret(%d), errno(%d)", command, ret, errno);
612 int _app2sd_delete_loopback_device(const char *loopback_device)
614 int ret = APP2EXT_SUCCESS;
616 ret = unlink(loopback_device);
618 if (errno == ENOENT) {
619 _W("unable to access file (%s)", loopback_device);
621 _E("unable to delete (%s)", loopback_device);
622 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
626 return APP2EXT_SUCCESS;
629 int _app2sd_create_file_system(const char *device_path)
631 int ret = APP2EXT_SUCCESS;
633 char err_buf[1024] = {0,};
635 if (device_path == NULL) {
637 return APP2EXT_ERROR_INVALID_ARGUMENTS;
640 /* Format the filesystem [create a filesystem]*/
641 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
642 fp = fopen(device_path, "r+");
644 strerror_r(errno, err_buf, sizeof(err_buf));
645 _E("unable to access (%s) error is (%d, %s)",
646 device_path, errno, err_buf);
647 return APP2EXT_ERROR_ACCESS_FILE;
651 ret = _xsystem(argv);
653 strerror_r(errno, err_buf, sizeof(err_buf));
654 _E("creating file system failed, error is (%s)",
656 return APP2EXT_ERROR_CREATE_FS;
661 static int _app2sd_create_dir_with_link(const char *application_path,
662 const char *pkgid, const char *dir_name, uid_t uid)
664 int ret = APP2EXT_SUCCESS;
665 char app_dir_mmc_path[FILENAME_MAX] = { 0, };
666 char app_dir_path[FILENAME_MAX] = { 0, };
668 snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
669 application_path, dir_name);
670 snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
671 application_path, dir_name);
673 ret = _app2sd_make_directory(app_dir_mmc_path, uid);
675 _E("create directory failed");
676 return APP2EXT_ERROR_CREATE_DIRECTORY;
679 if ((ret = symlink(app_dir_mmc_path,
680 app_dir_path)) < 0) {
681 if (errno == EEXIST) {
682 _D("file with symlink name present (%s)",
685 _E("symbolic link creation "
686 "failed, error no is (%d)", errno);
687 return APP2EXT_ERROR_CREATE_SYMLINK;
691 return APP2EXT_SUCCESS;
694 static int _app2sd_create_directory_entry(const char *application_path,
695 const char *pkgid, GList *dir_list, uid_t uid)
697 int ret = APP2EXT_SUCCESS;
699 app2ext_dir_details *dir_detail = NULL;
701 list = g_list_first(dir_list);
703 dir_detail = (app2ext_dir_details *)list->data;
704 if (dir_detail && dir_detail->name
705 && dir_detail->type == APP2EXT_DIR_RO) {
706 ret = _app2sd_create_dir_with_link(application_path,
707 pkgid, dir_detail->name, uid);
711 list = g_list_next(list);
713 return APP2EXT_SUCCESS;
716 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
717 const char *dev, int mount_type, GList *dir_list,
718 app2sd_cmd cmd, uid_t uid)
720 int ret = APP2EXT_SUCCESS;
722 char app_mmc_path[FILENAME_MAX] = { 0, };
723 char temp_path[FILENAME_MAX] = { 0, };
724 char err_buf[1024] = {0,};
725 struct timespec time = {
727 .tv_nsec = 1000 * 1000 * 200
731 _E("input param is NULL (%s)",
733 return APP2EXT_ERROR_INVALID_ARGUMENTS;
736 /* check directory existence */
737 fd = open(application_path, O_RDONLY|O_DIRECTORY);
739 _E("path(%s) error(%d)", application_path, errno);
740 return APP2EXT_ERROR_OPEN_DIR;
744 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
746 fd = open(app_mmc_path, O_RDONLY|O_DIRECTORY);
748 _E("path(%s) error(%d)", app_mmc_path, errno);
749 return APP2EXT_ERROR_OPEN_DIR;
753 nanosleep(&time, NULL); /* 200ms sleep */
754 _D("give a delay for mount");
756 switch (mount_type) {
758 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
759 MS_MGC_VAL | MS_RDONLY | MS_NOSUID, NULL)) < 0) {
760 _E("read only mount failed, " \
762 "dev is (%s) path is (%s)",
763 errno, dev, app_mmc_path);
764 ret = APP2EXT_ERROR_MOUNT;
768 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
769 MS_MGC_VAL | MS_NOSUID, NULL)) < 0) {
770 _E("read write mount failed, " \
771 "errono is (%d)", errno);
772 ret = APP2EXT_ERROR_MOUNT;
775 case MOUNT_TYPE_RW_NOEXEC:
776 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
777 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID, NULL)) < 0) {
778 _E("rwnx mount failed " \
779 "errono is (%d)", errno);
780 ret = APP2EXT_ERROR_MOUNT;
783 case MOUNT_TYPE_RD_REMOUNT:
784 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
785 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT | MS_NOSUID,
787 _E("read remount failed "
788 "errono is (%d)", errno);
789 ret = APP2EXT_ERROR_MOUNT;
792 case MOUNT_TYPE_RW_REMOUNT:
793 if ((ret = mount(dev, app_mmc_path, FS_TYPE,
794 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID, NULL)) < 0) {
795 _E("read write remount failed "
796 "errono(%d), errstr(%s)", errno,
797 strerror_r(errno, err_buf, sizeof(err_buf)));
798 ret = APP2EXT_ERROR_MOUNT;
802 _E("invalid mount type");
806 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
807 cmd == APP2SD_PRE_UPGRADE) {
808 ret = _app2sd_create_directory_entry(application_path,
809 pkgid, dir_list, uid);
812 if (mount_type != MOUNT_TYPE_RD &&
813 mount_type != MOUNT_TYPE_RD_REMOUNT) {
814 /* change lost+found permission */
815 snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
817 ret = _app2sd_make_directory(temp_path, uid);
819 _E("create directory(%s) failed", temp_path);
820 return APP2EXT_ERROR_CREATE_DIRECTORY;
827 int _app2sd_unmount_app_content(const char *application_path)
829 int ret = APP2EXT_SUCCESS;
830 char app_mmc_path[FILENAME_MAX] = { 0, };
831 char err_buf[1024] = {0,};
833 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
835 if ((ret = umount(app_mmc_path)) < 0) {
836 strerror_r(errno, err_buf, sizeof(err_buf));
837 _D("unable to umount the dir, ret(%d) error(%d, %s)",
838 ret, errno, err_buf);
844 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
846 int ret = APP2EXT_SUCCESS;
848 ret = _app2sd_copy_dir(src_path, arch_path);
849 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
850 char err_buf[1024] = {0,};
851 strerror_r(errno, err_buf, sizeof(err_buf));
852 _E("unable to copy from (%s) to (%s), err is (%s)",
853 src_path, arch_path, err_buf);
854 return APP2EXT_ERROR_MOVE;
857 ret = _app2sd_delete_directory((char *)src_path);
859 _E("unable to delete (%s)", src_path);
860 return APP2EXT_ERROR_DELETE_DIRECTORY;
866 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
867 uid_t uid, char *mmc_path, char **image_path)
869 int ret = APP2EXT_SUCCESS;
870 mode_t mode = DIR_PERMS;
871 char temp_dir_path[FILENAME_MAX] = { 0, };
872 char app_mmc_path[FILENAME_MAX] = { 0, };
873 char app_archive_path[FILENAME_MAX] = { 0, };
874 char application_path[FILENAME_MAX] = { 0, };
875 char loopback_device[FILENAME_MAX] = { 0, };
876 unsigned long long total_size = 0;
878 int reqd_disk_size = 0;
879 char *device_node = NULL;
880 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
883 int free_mmc_mem = 0;
886 app2ext_dir_details *dir_detail = NULL;
887 char err_buf[1024] = { 0,};
888 char *encoded_id = NULL;
890 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
891 if (encoded_id == NULL)
892 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
894 snprintf(loopback_device, sizeof(loopback_device), "%s/%s/%s",
895 mmc_path, EXTIMG_DIR, encoded_id);
897 _app2sd_set_application_path(pkgid, uid, application_path,
898 sizeof(application_path));
900 /* check whether application is in external memory or not */
901 fp = fopen(loopback_device, "r+");
903 _W("Already %s entry is present in the SD Card, " \
904 "delete entry and go on without return", pkgid);
906 _app2sd_force_clean(pkgid, application_path, loopback_device, uid);
909 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
911 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
914 ret = mkdir(app_mmc_path, mode);
916 if (errno != EEXIST) {
917 _E("unable to create directory for archiving," \
918 " error(%d)", errno);
919 return APP2EXT_ERROR_CREATE_DIRECTORY;
923 ret = mkdir(app_archive_path, mode);
925 if (errno != EEXIST) {
926 _E("unable to create directory for archiving," \
927 " error(%d)", errno);
928 return APP2EXT_ERROR_CREATE_DIRECTORY;
932 list = g_list_first(dir_list);
934 dir_detail = (app2ext_dir_details *)list->data;
935 if (dir_detail && dir_detail->name
936 && dir_detail->type == APP2EXT_DIR_RO) {
937 memset(temp_dir_path, '\0', sizeof(temp_dir_path));
938 snprintf(temp_dir_path, sizeof(temp_dir_path),
939 "%s/%s", application_path,
941 _D("cal size of app dirs, temp_dir_path(%s)",
944 _app2sd_calculate_dir_size(temp_dir_path);
946 list = g_list_next(list);
949 reqd_size = ((total_size) / (1024 * 1024)) + 2;
950 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
952 /* find avialable free memory in the MMC card */
953 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
955 _E("unable to get available free memory in MMC (%d)", ret);
956 return APP2EXT_ERROR_MMC_STATUS;
958 /* if avaialalbe free memory in MMC is less than
959 * required size + 5MB, return error
961 if (reqd_disk_size > free_mmc_mem) {
962 _E("insufficient memory in MMC for application installation (%d)",
964 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
966 /* create a loopback device */
967 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
968 (reqd_disk_size + PKG_BUF_SIZE));
970 _E("loopback node creation failed");
974 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
975 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
977 _E("dmcrypt setup device error(%d)", ret);
978 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
981 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
984 _E("dmcrypt open device error");
985 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
988 /* perform loopback encryption setup */
989 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
990 loopback_device, uid);
992 _E("loopback encryption setup failed");
993 return APP2EXT_ERROR_DO_LOSETUP;
995 _D("device_node (%s)", device_node);
996 /* check whether loopback device is associated with device node or not */
997 devi = _app2sd_find_associated_device_node(loopback_device);
999 _E("finding associated device node failed");
1000 ret = APP2EXT_ERROR_DO_LOSETUP;
1007 /* format the loopback file system */
1008 ret = _app2sd_create_file_system(device_node);
1010 _E("create ext4 filesystem failed");
1011 ret = APP2EXT_ERROR_CREATE_FS;
1015 list = g_list_first(dir_list);
1017 dir_detail = (app2ext_dir_details *)list->data;
1018 if (dir_detail && dir_detail->name
1019 && dir_detail->type == APP2EXT_DIR_RO) {
1020 memset(temp_dir_path, '\0', FILENAME_MAX);
1021 snprintf(temp_dir_path, sizeof(temp_dir_path),
1022 "%s/%s", application_path,
1024 _D("app2archive, temp_dir_path(%s)",
1026 ret = _app2sd_move_to_archive(temp_dir_path,
1029 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1030 _E("unable to access (%s)",
1033 _E("unable to copy from (%s) to (%s)",
1040 list = g_list_next(list);
1043 /* mount the loopback encrypted pseudo device on application installation path
1044 * as with Read Write permission
1046 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
1047 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
1053 list = g_list_first(dir_list);
1055 dir_detail = (app2ext_dir_details *)list->data;
1056 if (dir_detail && dir_detail->name
1057 && dir_detail->type == APP2EXT_DIR_RO) {
1058 memset(temp_dir_path, '\0', sizeof(temp_dir_path));
1059 snprintf(temp_dir_path, sizeof(temp_dir_path),
1060 "%s/%s", app_archive_path,
1062 _D("archive2mmc, temp_dir_path(%s)",
1064 ret = _app2sd_copy_dir(temp_dir_path,
1067 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1068 _E("unable to access (%s)",
1072 err_buf, sizeof(err_buf));
1073 _E("unable to copy from (%s) to (%s)," \
1076 app_mmc_path, err_buf);
1080 ret = _app2sd_delete_directory(temp_dir_path);
1082 _E("unable to delete (%s)", temp_dir_path);
1086 list = g_list_next(list);
1089 ret = _app2sd_delete_directory(app_archive_path);
1091 _E("unable to delete (%s)", app_archive_path);
1092 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
1096 *image_path = strdup(loopback_device);
1097 return APP2EXT_SUCCESS;
1109 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
1110 uid_t uid, char *mmc_path)
1112 int ret = APP2EXT_SUCCESS;
1113 mode_t mode = DIR_PERMS;
1114 char temp_dir_path[FILENAME_MAX] = { 0, };
1115 char app_mmc_path[FILENAME_MAX] = { 0, };
1116 char app_archive_path[FILENAME_MAX] = { 0, };
1117 char application_path[FILENAME_MAX] = { 0, };
1118 char loopback_device[FILENAME_MAX] = { 0, };
1119 char *device_node = NULL;
1122 app2ext_dir_details *dir_detail = NULL;
1124 int free_internal_mem = 0;
1125 unsigned long long temp = 0;
1126 char err_buf[1024] = {0,};
1127 char *encoded_id = NULL;
1129 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1130 if (encoded_id == NULL)
1131 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1133 snprintf(loopback_device, sizeof(loopback_device), "%s/%s/%s",
1134 mmc_path, EXTIMG_DIR, encoded_id);
1136 _app2sd_set_application_path(pkgid, uid, application_path,
1137 sizeof(application_path));
1139 /* check whether application is in external memory or not */
1140 fp = fopen(loopback_device, "r+");
1142 _E("application (%s) is not installed on SD Card",
1144 return APP2EXT_ERROR_FILE_ABSENT;
1150 /* find avialable free memory in the internal storage */
1151 ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
1152 &free_internal_mem);
1154 _E("unable to get available free memory in internal (%d)",
1156 return APP2EXT_ERROR_MMC_STATUS;
1159 fp = fopen(loopback_device, "r+");
1161 _E("app entry is not present in SD card");
1162 return APP2EXT_ERROR_INVALID_PACKAGE;
1166 /* get installed app size*/
1167 temp = _app2sd_calculate_file_size(loopback_device);
1168 reqd_size = (int)((temp) / (1024 * 1024));
1169 _D("reqd size is (%d)", reqd_size);
1171 if (reqd_size == 0) {
1172 _E("app entry is not present in SD Card");
1173 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1176 _I("reqd size: (%d)MB, free internal mem: (%d)MB",
1177 reqd_size, free_internal_mem);
1179 /* if avaialalbe free memory in internal storage is
1180 * less than required size, return error
1182 if (reqd_size > free_internal_mem) {
1183 _E("innsufficient memory in internal storage" \
1184 " for application installation (%d)", ret);
1185 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1188 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1190 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1192 device_node = _app2sd_find_associated_device_node(loopback_device);
1194 if (NULL == device_node) {
1195 /* do loopback setup */
1196 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1197 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1198 false, uid, &device_node);
1200 _E("dmcrypt open device error(%d)", ret);
1201 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1204 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1205 loopback_device, uid);
1206 if (device_node == NULL) {
1207 _E("loopback encryption setup failed");
1208 return APP2EXT_ERROR_DO_LOSETUP;
1212 ret = _app2sd_mount_app_content(application_path,
1213 pkgid, device_node, MOUNT_TYPE_RW,
1214 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1217 ret = APP2EXT_ERROR_MOUNT_PATH;
1221 /* do re-mounting */
1222 ret = _app2sd_mount_app_content(application_path,
1223 pkgid, device_node, MOUNT_TYPE_RW_REMOUNT,
1224 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1226 _E("re-mount failed");
1227 ret = APP2EXT_ERROR_MOUNT_PATH;
1232 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
1234 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
1237 ret = mkdir(app_archive_path, mode);
1239 if (errno != EEXIST) {
1240 _E("unable to create directory for archiving," \
1241 " error(%d)", errno);
1242 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
1247 list = g_list_first(dir_list);
1249 dir_detail = (app2ext_dir_details *)list->data;
1250 if (dir_detail && dir_detail->name
1251 && dir_detail->type == APP2EXT_DIR_RO) {
1252 /* archiving code */
1253 memset(temp_dir_path, '\0', sizeof(temp_dir_path));
1254 snprintf(temp_dir_path, sizeof(temp_dir_path),
1255 "%s/%s", app_mmc_path,
1257 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1258 ret = _app2sd_copy_dir(temp_dir_path,
1261 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1262 _E("unable to access (%s)",
1266 err_buf, sizeof(err_buf));
1267 _E("unable to copy from (%s) to (%s),"
1270 app_archive_path, err_buf);
1275 /* delete the symbolic link files [bin, lib, res]*/
1276 memset(temp_dir_path, '\0', sizeof(temp_dir_path));
1277 snprintf(temp_dir_path, sizeof(temp_dir_path),
1278 "%s/%s", application_path,
1280 _D("unlink, temp_dir_path(%s)", temp_dir_path);
1281 ret = unlink(temp_dir_path);
1283 if (errno == ENOENT) {
1284 _W("directory (%s) does not exist",
1287 _E("unable to remove the symbolic link file (%s)," \
1288 " it is already unlinked",
1294 /* Copy content to destination */
1295 memset(temp_dir_path, '\0', sizeof(temp_dir_path));
1296 snprintf(temp_dir_path, sizeof(temp_dir_path),
1297 "%s/%s", app_archive_path,
1299 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1300 ret = _app2sd_copy_dir(temp_dir_path, application_path);
1302 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1303 _E("unable to access (%s)",
1307 err_buf, sizeof(err_buf));
1308 _E("unable to copy from (%s) to (%s) " \
1311 application_path, err_buf);
1316 list = g_list_next(list);
1319 _D("copying file completed");
1320 ret = _app2sd_unmount_app_content(application_path);
1322 _E("unable to unmount SD directory for app (%s)",
1325 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1326 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1328 _E("close dmcrypt device error(%d)", ret);
1330 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1332 _E("unable to detach loopback setup for (%s)",
1336 ret = _app2sd_delete_loopback_device(loopback_device);
1338 _E("unable to delete the loopback device for (%s)",
1341 ret = _app2sd_delete_directory(app_mmc_path);
1343 _E("unable to delete (%s)", app_mmc_path);
1345 ret = _app2sd_delete_directory(app_archive_path);
1347 _E("unable to delete (%s)", app_archive_path);
1349 /* remove passwrd from DB */
1350 ret = _app2sd_initialize_db();
1352 _E("app2sd db initialize failed");
1354 ret = _app2sd_remove_info_from_db(pkgid, uid);
1356 _E("cannot remove info from db");
1358 return APP2EXT_SUCCESS;
1369 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1370 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
1372 int ret = APP2EXT_SUCCESS;
1374 switch (move_type) {
1375 case APP2EXT_MOVE_TO_EXT:
1376 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1377 uid, mmc_path, image_path);
1379 _E("move app to external memory failed(%d)", ret);
1383 case APP2EXT_MOVE_TO_PHONE:
1384 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1387 _E("move app to internal memory failed(%d)", ret);
1392 _E("invalid argument");
1393 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1399 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1401 char path[FILENAME_MAX] = { 0, };
1402 int ret = APP2EXT_SUCCESS;
1404 app2ext_dir_details *dir_detail = NULL;
1406 list = g_list_first(dir_list);
1408 dir_detail = (app2ext_dir_details *)list->data;
1409 if (dir_detail && dir_detail->name
1410 && dir_detail->type == APP2EXT_DIR_RO) {
1411 memset((void *)&path, '\0', sizeof(path));
1412 snprintf(path, sizeof(path), "%s/%s", src,
1414 ret = _app2sd_copy_dir(path, dest);
1416 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1417 _E("unable to access (%s)", path);
1419 _E("unable to copy from (%s) " \
1420 "to (%s), errno is (%d)",
1422 return APP2EXT_ERROR_MOVE;
1426 list = g_list_next(list);
1429 return APP2EXT_SUCCESS;
1432 int _app2sd_duplicate_device(const char *pkgid,
1433 const char *loopback_device,
1434 const char *temp_pkgid,
1435 const char *temp_application_path,
1436 const char *temp_loopback_device,
1437 GList *dir_list, char *dev_node, int size,
1442 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1444 char *result = NULL;
1445 char *passwd = NULL;
1448 /* create a new loopback device */
1449 ret = _app2sd_create_loopback_device(temp_pkgid,
1450 temp_loopback_device, (size + PKG_BUF_SIZE));
1452 _E("package already present");
1456 /* perform loopback encryption setup */
1457 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1458 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1459 temp_loopback_device, uid);
1461 _E("dmcrypt duplicate encryption setup failed");
1462 _app2sd_delete_loopback_device(temp_loopback_device);
1463 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1466 /* get password for loopback encryption */
1467 ret = _app2sd_initialize_db();
1469 _E("app2sd db initialize failed");
1470 return APP2EXT_ERROR_DB_INITIALIZE;
1473 if ((passwd = _app2sd_get_password_from_db(pkgid, uid)) == NULL) {
1474 passwd = (char *)_app2sd_generate_password();
1475 if (NULL == passwd) {
1476 _E("unable to generate password");
1477 return APP2EXT_ERROR_PASSWD_GENERATION;
1479 if ((ret = _app2sd_set_info_in_db(pkgid,
1480 passwd, loopback_device, uid)) < 0) {
1481 _E("unable to save info");
1484 return APP2EXT_ERROR_SQLITE_REGISTRY;
1489 dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1490 temp_pkgid, temp_loopback_device, passwd, uid);
1492 _E("losetup failed, device node is (%s)", dev_node);
1493 _app2sd_delete_loopback_device(temp_loopback_device);
1496 return APP2EXT_ERROR_DO_LOSETUP;
1500 _D("duplicate setup SUCCESS");
1502 /* check whether loopback device is associated with
1503 * device node or not
1505 devi = _app2sd_find_associated_device_node(temp_loopback_device);
1507 _E("finding associated device node failed");
1508 err_res = APP2EXT_ERROR_DO_LOSETUP;
1511 _D("losetup SUCCESS");
1514 /* format the loopback file system */
1515 ret = _app2sd_create_file_system(dev_node);
1517 _E("creating fs failed");
1518 err_res = APP2EXT_ERROR_CREATE_FS;
1521 _D("create filesystem SUCCESS");
1523 /* do mounting for new dev*/
1524 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1525 dev_node, MOUNT_TYPE_RW, dir_list,
1526 APP2SD_PRE_UPGRADE, uid);
1528 _E("remount failed");
1529 err_res = APP2EXT_ERROR_MOUNT_PATH;
1533 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1540 return APP2EXT_SUCCESS;
1544 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1545 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1547 _E("close dmcrypt device error(%d)", ret);
1549 result = _app2sd_detach_loop_device(dev_node);
1555 _app2sd_delete_loopback_device(temp_loopback_device);
1563 int _app2sd_update_loopback_device_size(const char *pkgid,
1564 const char *loopback_device,
1565 const char *application_path,
1566 const char *temp_pkgid,
1567 const char *temp_loopback_device,
1568 const char *temp_application_path,
1569 int size, GList *dir_list,
1573 char *device_node = NULL;
1574 char *old_device_node = NULL;
1576 char app_mmc_path[FILENAME_MAX] = { 0, };
1577 char temp_app_mmc_path[FILENAME_MAX] = { 0, };
1579 ret = _app2sd_duplicate_device(pkgid, loopback_device,
1580 temp_pkgid, temp_application_path, temp_loopback_device,
1581 dir_list, device_node, size, uid);
1583 _E("creating duplicate device failed");
1587 /* get the associated device node for SD card applicatione */
1588 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1590 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1592 old_device_node = _app2sd_find_associated_device_node(loopback_device);
1594 if (NULL == old_device_node) {
1595 /* do loopback setup */
1596 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1597 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1598 false, uid, &old_device_node);
1600 _E("dmcrypt open device error");
1601 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1605 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1606 loopback_device, uid);
1607 if (old_device_node == NULL) {
1608 _E("loopback encryption setup failed");
1609 err_res = APP2EXT_ERROR_DO_LOSETUP;
1614 ret = _app2sd_mount_app_content(application_path, pkgid,
1615 old_device_node, MOUNT_TYPE_RW, dir_list,
1616 APP2SD_PRE_UPGRADE, uid);
1618 _E("remount failed");
1619 err_res = APP2EXT_ERROR_MOUNT_PATH;
1622 /* do re-mounting */
1623 ret = _app2sd_mount_app_content(application_path, pkgid,
1624 old_device_node, MOUNT_TYPE_RW_REMOUNT, dir_list,
1625 APP2SD_PRE_UPGRADE, uid);
1627 _E("remount failed");
1628 err_res = APP2EXT_ERROR_MOUNT_PATH;
1632 snprintf(app_mmc_path, sizeof(app_mmc_path),
1633 "%s/.mmc", application_path);
1634 snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1635 "%s/.mmc", temp_application_path);
1637 ret = _app2sd_copy_ro_content(app_mmc_path,
1638 temp_app_mmc_path, dir_list);
1640 _E("copy ro content failed");
1644 ret = _app2sd_unmount_app_content(application_path);
1646 _E("unable to unmount the SD application");
1647 err_res = APP2EXT_ERROR_UNMOUNT;
1650 ret = _app2sd_unmount_app_content(temp_application_path);
1652 _E("unable to unmount the SD application");
1653 err_res = APP2EXT_ERROR_UNMOUNT;
1657 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1658 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1660 _E("close dmcrypt device error(%d)", ret);
1661 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1665 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1667 _E("close dmcrypt device error(%d)", ret);
1668 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1672 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1674 _E("unable to remove loopback setup");
1675 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1678 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1680 _E("unable to remove loopback setup");
1681 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1686 ret = _app2sd_delete_directory(loopback_device);
1688 _E("unable to delete (%s)", loopback_device);
1689 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1693 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1695 _E("unable to rename (%s)", temp_loopback_device);
1696 err_res = APP2EXT_ERROR_MOVE;
1700 ret = _app2sd_delete_directory(temp_application_path);
1702 _E("unable to delete (%s)", temp_application_path);
1703 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1707 return APP2EXT_SUCCESS;
1710 if (old_device_node) {
1711 free(old_device_node);
1712 old_device_node = NULL;
1715 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1716 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1718 _E("close dmcrypt device error(%d)", ret);
1720 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1723 _E("close dmcrypt device error(%d)", ret);
1725 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1727 _E("unable to remove loopback setup");
1729 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1731 _E("unable to remove loopback setup");
1734 _app2sd_delete_loopback_device(temp_loopback_device);
1736 ret = _app2sd_delete_directory(temp_application_path);
1738 _E("unable to delete (%s)", temp_application_path);
1743 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1744 const char *loopback_device, uid_t uid)
1746 int ret = APP2EXT_SUCCESS;
1748 /* unmount the loopback encrypted pseudo device from the application installation path */
1749 ret = _app2sd_unmount_app_content(application_path);
1751 _W("unable to unmount the app content (%d)", ret);
1753 /* detach the loopback encryption setup for the application */
1754 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1755 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1757 _W("close dmcrypt device error (%d)", ret);
1759 ret = _app2sd_remove_all_loopback_encryption_setups(loopback_device);
1761 _W("unable to detach the loopback encryption setup for the application");
1764 /* delete the loopback device from the SD card */
1765 ret = _app2sd_delete_loopback_device(loopback_device);
1767 _W("unable to detach the loopback encryption setup for the application");
1769 /* delete symlink */
1770 _app2sd_delete_symlink(application_path);
1772 /* remove passwrd from DB */
1773 ret = _app2sd_initialize_db();
1775 _W("app2sd db initialize failed");
1777 ret = _app2sd_remove_info_from_db(pkgid, uid);
1779 _W("cannot remove info from db");