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.
24 #include <sys/xattr.h>
25 #include <sys/types.h>
35 #include <openssl/sha.h>
39 #include <sys/statvfs.h>
42 #include <app2sd_internals.h>
43 #include <app2sd_interface.h>
45 int _is_global(uid_t uid)
47 if (uid == OWNER_ROOT || uid == GLOBAL_USER)
53 static int _app2sd_setup_path(const char* path, const char *label, uid_t uid)
55 int ret = APP2EXT_SUCCESS;
57 struct passwd *pwd_result;
58 char buf[1024] = { 0, };
60 ret = lsetxattr(path, "security.SMACK64TRANSMUTE", "TRUE", 4, 0);
62 _E("set transmute error");
63 return APP2EXT_ERROR_ACCESS_FILE;
65 ret = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
67 _E("set label(%s) error", label);
68 return APP2EXT_ERROR_ACCESS_FILE;
70 ret = chmod(path, 0755);
72 _E("change file permission error");
73 return APP2EXT_ERROR_ACCESS_FILE;
76 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
77 if (ret != 0 || pwd_result == NULL) {
78 _E("get uid failed(%d)", ret);
79 return APP2EXT_ERROR_ACCESS_FILE;
82 _D("uid(%d), gid(%d)", uid, pwd.pw_gid);
83 ret = chown(path, uid, pwd.pw_gid);
85 _E("change file owner error");
86 return APP2EXT_ERROR_ACCESS_FILE;
92 static int _app2sd_apply_app_smack(const char *application_path,
93 const char *pkgid, GList* dir_list, uid_t uid)
95 int ret = APP2EXT_SUCCESS;
97 app2ext_dir_details* dir_detail = NULL;
98 char temp_dir_path[FILENAME_MAX] = { 0, };
99 char label[FILENAME_MAX] = { 0, };
101 snprintf(label, FILENAME_MAX, "User::Pkg::%s::RO", pkgid);
102 list = g_list_first(dir_list);
104 dir_detail = (app2ext_dir_details *)list->data;
105 if (dir_detail && dir_detail->name
106 && dir_detail->type == APP2EXT_DIR_RO) {
107 memset(temp_dir_path, '\0', FILENAME_MAX);
108 snprintf(temp_dir_path, FILENAME_MAX,
109 "%s/%s", application_path,
111 _D("set label(%s) to path(%s)",
112 label, temp_dir_path);
113 ret = _app2sd_setup_path(temp_dir_path, /* label */ "*", uid);
115 _E("unable to smack (%s)", label);
116 return APP2EXT_ERROR_MOVE;
119 list = g_list_next(list);
122 return APP2EXT_SUCCESS;
125 char *_app2sd_find_associated_device_node(const char *loopback_device)
127 char *ret_result = NULL;
130 char dev[FILENAME_MAX] = { 0, };
131 char *devnode = NULL;
133 result = (char *)_app2sd_find_associated_device(loopback_device);
134 if (result == NULL) {
135 _D("there is no the associated file (%s)", loopback_device);
139 /* process the string*/
140 snprintf(dev, FILENAME_MAX - 1, "%s", result);
142 if (strstr(dev, "dev") == NULL) {
143 _E("unable to find the associated file");
147 char *saveptr = NULL;
148 ret_result = strtok_r(dev, delims, &saveptr);
150 devnode = strdup(ret_result);
158 char *_app2sd_create_loopdevice_node(void)
160 char *ret_result = NULL;
161 mode_t mode = DIR_PERMS;
163 int ret = APP2EXT_SUCCESS;
167 result = (char *)_app2sd_find_free_device();
168 _D("find_free_device(%s)", result);
170 /* validate the result */
171 if (result == NULL || strstr(result, "/dev") == NULL) {
172 _D("no device found, creating device node");
179 char dev_path[BUF_SIZE] = { 0, };
180 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
181 while ((fp = fopen(dev_path, "r+")) != NULL) {
183 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
184 _D("next dev path for checking is (%s)",
188 _D("device node candidate is (%s)", dev_path);
190 dev_node = makedev(DEV_MAJOR, count);
191 ret = mknod(dev_path, S_IFBLK | mode, dev_node);
193 _E("error while creating the device node: errno is (%d)",
197 ret_result = (char *)malloc(strlen(dev_path) + 1);
198 if (ret_result == NULL) {
199 _E("unable to allocate memory");
202 memset(ret_result, '\0', strlen(dev_path) + 1);
203 memcpy(ret_result, dev_path, strlen(dev_path));
205 ret_result = (char *)malloc(strlen(result) + 1);
206 if (ret_result == NULL) {
212 memset(ret_result, '\0', strlen(result) + 1);
213 if (strlen(result) > 0) {
214 memcpy(ret_result, result, strlen(result) - 1);
223 char *_app2sd_do_loopback_encryption_setup(const char *pkgid,
224 const char *loopback_device, uid_t uid)
226 int ret = APP2EXT_SUCCESS;
229 char *device_node = NULL;
232 _E("invalid argument");
236 /* get password for loopback encryption */
237 ret = _app2sd_initialize_db();
239 _E("app2sd db initialize failed");
243 if ((passwd = _app2sd_get_password_from_db(pkgid)) == NULL) {
244 passwd = (char *)_app2sd_generate_password(pkgid);
245 if (NULL == passwd) {
246 _E("unable to generate password");
249 if ((ret = _app2sd_set_password_in_db(pkgid,
251 _E("unable to save password");
259 /* get free device node*/
260 device_node = _app2sd_create_loopdevice_node();
261 if (NULL == device_node) {
264 _E("unable to find free loopback node");
268 _D("device_node (%s)", device_node);
270 result = (char *)_app2sd_encrypt_device(device_node,
271 loopback_device, passwd);
272 if (result == NULL) {
273 _E("encryption failed");
278 _D("result (%s)", result);
287 char *_app2sd_do_loopback_duplicate_encryption_setup(const char *pkgid,
288 const char *temp_pkgid, const char *temp_loopback_device,
291 int ret = APP2EXT_SUCCESS;
294 char *device_node = NULL;
296 if (pkgid == NULL || temp_pkgid == NULL ||
297 temp_loopback_device == NULL) {
298 _E("invalid argument");
302 /* get password for loopback encryption */
303 ret = _app2sd_initialize_db();
305 _E("app2sd db initialize failed");
309 if ((passwd = _app2sd_get_password_from_db(pkgid)) == NULL) {
310 passwd = (char *)_app2sd_generate_password(pkgid);
311 if (NULL == passwd) {
312 _E("unable to generate password");
315 if ((ret = _app2sd_set_password_in_db(pkgid,
317 _E("unable to save password");
326 /* get free device node*/
327 device_node = _app2sd_create_loopdevice_node();
328 if (NULL == device_node) {
331 _E("unable to find free loopback node");
334 result = (char *)_app2sd_encrypt_device(device_node,
335 temp_loopback_device, passwd);
336 if (result == NULL) {
337 _E("encryption failed");
342 if (strlen(result) == 0) {
349 _E("error is (%s)", result);
361 int _app2sd_remove_loopback_encryption_setup(const char *loopback_device)
363 int ret = APP2EXT_SUCCESS;
365 char *dev_node = NULL;
367 if ((dev_node = _app2sd_find_associated_device_node(loopback_device))
369 _E("Unable to find the association");
370 ret = APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE;
373 result = (char *)_app2sd_detach_loop_device(dev_node);
374 if (result == NULL) {
375 _E("error in detaching");
376 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
390 int _app2sd_remove_all_loopback_encryption_setups(const char *loopback_device)
392 int ret = APP2EXT_SUCCESS;
394 char *dev_node = NULL;
397 _app2sd_find_associated_device_node(loopback_device))
399 _E("finish to find the association");
400 ret = APP2EXT_SUCCESS;
404 _D("find node (%s)", dev_node);
406 result = (char *)_app2sd_detach_loop_device(dev_node);
407 if (result == NULL) {
408 _E("error in detaching");
409 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
424 int _app2sd_create_loopback_device(const char *pkgid,
425 const char *loopback_device, int size)
427 int ret = APP2EXT_SUCCESS;
428 char command[FILENAME_MAX] = { 0, };
429 char buff[BUF_SIZE] = { 0, };
432 if (NULL == pkgid || size <= 0) {
433 _E("invalid argument");
434 return APP2EXT_ERROR_INVALID_ARGUMENTS;
436 snprintf(command, FILENAME_MAX - 1, "of=%s", loopback_device);
437 snprintf(buff, BUF_SIZE - 1, "count=%d", size);
439 const char *argv1[] =
440 { "dd", "if=/dev/zero", command, "bs=1M", buff, NULL };
442 if ((fp = fopen(loopback_device, "r+")) != NULL) {
443 _E("encrypted file already exists (%s)",
446 return APP2EXT_ERROR_PKG_EXISTS;
449 ret = _xsystem(argv1);
451 _E("command (%s) failed", command);
456 int _app2sd_delete_loopback_device(const char *loopback_device)
458 int ret = APP2EXT_SUCCESS;
460 ret = unlink(loopback_device);
462 if (errno == ENOENT) {
463 _E("unable to access file (%s)", loopback_device);
465 _E("unable to delete (%s)", loopback_device);
466 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
473 int _app2sd_create_file_system(const char *device_path)
475 int ret = APP2EXT_SUCCESS;
477 char err_buf[1024] = {0,};
479 if (device_path == NULL) {
481 return APP2EXT_ERROR_INVALID_ARGUMENTS;
484 /* Format the filesystem [create a filesystem]*/
485 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
486 fp = fopen(device_path, "r+");
488 strerror_r(errno, err_buf, sizeof(err_buf));
489 _E("unable to access (%s) error is (%d, %s)",
490 device_path, errno, err_buf);
491 return APP2EXT_ERROR_ACCESS_FILE;
495 ret = _xsystem(argv);
497 strerror_r(errno, err_buf, sizeof(err_buf));
498 _E("creating file system failed, error is (%s)",
500 return APP2EXT_ERROR_CREATE_FS;
505 static int _app2sd_create_dir_with_link(const char *application_path,
506 const char *pkgid, const char *dir_name, uid_t uid)
508 mode_t mode = DIR_PERMS;
509 int ret = APP2EXT_SUCCESS;
510 char application_dir_mmc_path[FILENAME_MAX] = { 0, };
511 char application_dir_path[FILENAME_MAX] = { 0, };
512 char label[FILENAME_MAX] = { 0, };
514 snprintf(application_dir_mmc_path, FILENAME_MAX - 1, "%s/.mmc/%s",
515 application_path, dir_name);
516 snprintf(application_dir_path, FILENAME_MAX, "%s/%s",
517 application_path, dir_name);
518 snprintf(label, FILENAME_MAX, "User::Pkg::%s::RO", pkgid);
520 ret = mkdir(application_dir_mmc_path, mode);
522 if (errno != EEXIST) {
523 _E("create directory failed," \
524 " error no is (%d)", errno);
525 return APP2EXT_ERROR_CREATE_DIRECTORY;
529 if ((ret = symlink(application_dir_mmc_path,
530 application_dir_path)) < 0) {
531 if (errno == EEXIST) {
532 _D("file with symlink name present (%s)",
533 application_dir_path);
535 _E("symbolic link creation "
536 "failed, error no is (%d)", errno);
537 return APP2EXT_ERROR_CREATE_SYMLINK;
541 ret = _app2sd_setup_path(application_dir_path, /* label */ "*", uid);
543 _E ("unable to smack (%s)", application_dir_path);
544 return APP2EXT_ERROR_MOVE;
547 ret = _app2sd_setup_path(application_dir_mmc_path, /* label */ "*", uid);
549 _E ("unable to smack (%s)", application_dir_mmc_path);
550 return APP2EXT_ERROR_MOVE;
556 static int _app2sd_create_directory_entry(const char *application_path,
557 const char *pkgid, GList* dir_list, uid_t uid)
559 int ret = APP2EXT_SUCCESS;
561 app2ext_dir_details* dir_detail = NULL;
563 list = g_list_first(dir_list);
565 dir_detail = (app2ext_dir_details *)list->data;
566 if (dir_detail && dir_detail->name
567 && dir_detail->type == APP2EXT_DIR_RO) {
568 ret = _app2sd_create_dir_with_link(application_path,
569 pkgid, dir_detail->name, uid);
574 list = g_list_next(list);
576 return APP2EXT_SUCCESS;
579 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
580 const char *dev, int mount_type, GList* dir_list,
581 app2sd_cmd cmd, uid_t uid)
583 int ret = APP2EXT_SUCCESS;
584 mode_t mode = DIR_PERMS;
585 char application_mmc_path[FILENAME_MAX] = { 0, };
586 char temp_path[FILENAME_MAX] = { 0, };
587 char label[FILENAME_MAX] = { 0, };
588 struct timespec time = {
590 .tv_nsec = 1000 * 1000 * 200
594 _E("input param is NULL (%s)",
596 return APP2EXT_ERROR_INVALID_ARGUMENTS;
599 ret = mkdir(application_path, mode);
601 if (errno != EEXIST) {
602 _E("create directory failed," \
603 " error no is (%d)", errno);
604 return APP2EXT_ERROR_CREATE_DIRECTORY;
607 ret = _app2sd_setup_path(application_path, "*", uid);
609 _E ("unable to smack (%s)", application_path);
610 return APP2EXT_ERROR_ACCESS_FILE;
614 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
616 ret = mkdir(application_mmc_path, mode);
618 if (errno != EEXIST) {
619 _E("create directory failed," \
620 " error no is (%d)", errno);
621 return APP2EXT_ERROR_CREATE_DIRECTORY;
624 snprintf(label, FILENAME_MAX, "User::Pkg::%s::RO", pkgid);
625 ret = _app2sd_setup_path(application_mmc_path, /* label */ "*", uid);
627 _E ("unable to smack (%s)", application_mmc_path);
628 return APP2EXT_ERROR_ACCESS_FILE;
632 nanosleep(&time, NULL); /* 200ms sleep */
633 _D("give a delay for mount");
635 switch (mount_type) {
637 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
638 MS_MGC_VAL | MS_RDONLY | MS_NOSUID, NULL)) < 0) {
639 _E("read only mount failed, " \
641 "dev is (%s) path is (%s)",
642 errno, dev, application_mmc_path);
643 ret = APP2EXT_ERROR_MOUNT;
647 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
648 MS_MGC_VAL | MS_NOSUID, NULL)) < 0) {
649 _E("read write mount failed, " \
650 "errono is (%d)", errno);
651 ret = APP2EXT_ERROR_MOUNT;
654 case MOUNT_TYPE_RW_NOEXEC:
655 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
656 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID, NULL)) < 0) {
657 _E("rwnx mount failed " \
658 "errono is (%d)", errno);
659 ret = APP2EXT_ERROR_MOUNT;
662 case MOUNT_TYPE_RD_REMOUNT:
663 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
664 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT | MS_NOSUID,
666 _E("read remount failed "
667 "errono is (%d)", errno);
668 ret = APP2EXT_ERROR_MOUNT;
671 case MOUNT_TYPE_RW_REMOUNT:
672 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
673 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID, NULL)) < 0) {
674 _E("read write remount failed "
675 "erro no is (%d)", errno);
676 ret = APP2EXT_ERROR_MOUNT;
680 _E("invalid mount type");
684 if (cmd == APP2SD_PRE_UNINSTALL || cmd == APP2SD_PRE_UPGRADE) {
685 /* delete lost+found dir */
686 snprintf(temp_path, FILENAME_MAX - 1, "%s/lost+found",
687 application_mmc_path);
688 ret = _app2sd_delete_directory(temp_path);
689 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
690 _E("unable to delete (%s)", temp_path);
691 return APP2EXT_ERROR_DELETE_DIRECTORY;
695 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
696 cmd == APP2SD_PRE_UPGRADE) {
697 ret = _app2sd_create_directory_entry(application_path,
698 pkgid, dir_list, uid);
704 int _app2sd_unmount_app_content(const char *application_path)
706 int ret = APP2EXT_SUCCESS;
707 char application_dir_mmc_path[FILENAME_MAX] = { 0, };
708 char err_buf[1024] = {0,};
710 snprintf(application_dir_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
712 if ((ret = umount(application_dir_mmc_path)) < 0) {
713 strerror_r(errno, err_buf, sizeof(err_buf));
714 _E("unable to umount the dir, ret(%d) error(%d, %s)",
715 ret, errno, err_buf);
721 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
723 int ret = APP2EXT_SUCCESS;
725 ret = _app2sd_copy_dir(src_path, arch_path);
726 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
727 char err_buf[1024] = {0,};
728 strerror_r(errno, err_buf, sizeof(err_buf));
729 _E("unable to copy from (%s) to (%s), err is (%s)",
730 src_path, arch_path, err_buf);
731 return APP2EXT_ERROR_MOVE;
734 ret = _app2sd_delete_directory((char *)src_path);
735 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
736 _E("unable to delete (%s)", src_path);
737 return APP2EXT_ERROR_DELETE_DIRECTORY;
743 int _app2sd_move_app_to_external(const char *pkgid, GList* dir_list, uid_t uid)
745 int ret = APP2EXT_SUCCESS;
746 char temp_dir_path[FILENAME_MAX] = { 0, };
747 char application_mmc_path[FILENAME_MAX] = { 0, };
748 char application_archive_path[FILENAME_MAX] = { 0, };
749 char application_path[FILENAME_MAX] = { 0, };
750 char loopback_device[FILENAME_MAX] = { 0, };
751 unsigned long long total_size = 0;
753 int reqd_disk_size = 0;
754 char *device_node = NULL;
756 mode_t mode = DIR_PERMS;
757 int free_mmc_mem = 0;
760 app2ext_dir_details* dir_detail = NULL;
761 char err_buf[1024] = {0,};
763 /* check whether MMC is present or not */
764 ret = _app2sd_check_mmc_status();
766 _E("MMC not preset OR Not ready(%d)", ret);
767 return APP2EXT_ERROR_MMC_STATUS;
770 if (_is_global(uid)) {
771 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
772 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
773 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
776 tzplatform_set_user(uid);
777 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
778 tzplatform_getenv(TZ_USER_APP), pkgid);
779 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
780 APP2SD_PATH, tzplatform_getenv(TZ_USER_NAME), pkgid);
781 tzplatform_reset_user();
783 _D("application_path = (%s)", application_path);
784 _D("loopback_device = (%s)", loopback_device);
786 /* check whether application is in external memory or not */
787 fp = fopen(loopback_device, "r+");
789 _W("Already %s entry is present in the SD Card, " \
790 "delete entry and go on without return", pkgid);
792 app2sd_usr_force_clean(pkgid, uid);
795 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
797 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
799 _D("application_mmc_path = (%s)", application_mmc_path);
800 _D("application_archive_path = (%s)", application_archive_path);
802 ret = mkdir(application_archive_path, mode);
804 if (errno != EEXIST) {
805 _E("unable to create directory for archiving," \
806 " error(%d)", errno);
807 return APP2EXT_ERROR_CREATE_DIRECTORY;
811 list = g_list_first(dir_list);
813 dir_detail = (app2ext_dir_details *)list->data;
814 if (dir_detail && dir_detail->name
815 && dir_detail->type == APP2EXT_DIR_RO) {
816 memset(temp_dir_path, '\0', FILENAME_MAX);
817 snprintf(temp_dir_path, FILENAME_MAX,
818 "%s/%s", application_path,
820 _D("cal size of app dirs, temp_dir_path(%s)",
823 _app2sd_calculate_dir_size(temp_dir_path);
825 list = g_list_next(list);
828 reqd_size = ((total_size) / ( 1024 * 1024)) + 2;
829 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
831 /* find avialable free memory in the MMC card */
832 ret = _app2sd_get_available_free_memory(MMC_PATH, &free_mmc_mem);
834 _E("unable to get available free memory in MMC (%d)", ret);
835 return APP2EXT_ERROR_MMC_STATUS;
837 /* if avaialalbe free memory in MMC is less than
838 * required size + 5MB, return error
840 if (reqd_disk_size > free_mmc_mem) {
841 _E("insufficient memory in MMC for application installation (%d)",
843 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
845 /* create a loopback device */
846 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
847 (reqd_disk_size + PKG_BUF_SIZE));
849 _E("loopback node creation failed");
852 /* perform loopback encryption setup */
853 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
854 loopback_device, uid);
856 _E("loopback encryption setup failed");
857 return APP2EXT_ERROR_DO_LOSETUP;
859 _D("device_node (%s)", device_node);
860 /* check whether loopback device is associated with device node or not */
861 devi = _app2sd_find_associated_device_node(loopback_device);
863 _E("finding associated device node failed");
864 return APP2EXT_ERROR_DO_LOSETUP;
869 /* format the loopback file system */
870 ret = _app2sd_create_file_system(device_node);
872 _E("create ext4 filesystem failed");
873 return APP2EXT_ERROR_CREATE_FS;
876 list = g_list_first(dir_list);
878 dir_detail = (app2ext_dir_details *)list->data;
879 if (dir_detail && dir_detail->name
880 && dir_detail->type == APP2EXT_DIR_RO) {
881 memset(temp_dir_path, '\0', FILENAME_MAX);
882 snprintf(temp_dir_path, FILENAME_MAX,
883 "%s/%s", application_path,
885 _D("app2archive, temp_dir_path(%s)",
887 ret = _app2sd_move_to_archive(temp_dir_path,
888 application_archive_path);
890 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
891 _E("unable to access (%s)",
894 _E("unable to copy from (%s) to (%s)",
896 application_archive_path);
901 list = g_list_next(list);
904 /* mount the loopback encrypted pseudo device on application installation path
905 * as with Read Write permission
907 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
908 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
914 list = g_list_first(dir_list);
916 dir_detail = (app2ext_dir_details *)list->data;
917 if (dir_detail && dir_detail->name
918 && dir_detail->type == APP2EXT_DIR_RO) {
919 memset(temp_dir_path, '\0', FILENAME_MAX);
920 snprintf(temp_dir_path, FILENAME_MAX,
921 "%s/%s", application_archive_path,
923 _D("archive2mmc, temp_dir_path(%s)",
925 ret = _app2sd_copy_dir(temp_dir_path,
926 application_mmc_path);
928 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
929 _E("unable to access (%s)",
933 err_buf, sizeof(err_buf));
934 _E("unable to copy from (%s) to (%s)," \
937 application_mmc_path, err_buf);
941 ret = _app2sd_delete_directory(temp_dir_path);
943 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
944 _E("unable to access (%s)",
947 _E("unable to delete (%s)",
953 list = g_list_next(list);
956 ret = _app2sd_delete_directory(application_archive_path);
958 _E("unable to delete (%s)", application_archive_path);
959 return APP2EXT_ERROR_DELETE_DIRECTORY;
962 ret = _app2sd_apply_app_smack(application_path, pkgid, dir_list, uid);
964 _E("unable to apply app smack");
965 return APP2EXT_ERROR_MOVE;
968 /* re-mount the loopback encrypted pseudo device on application installation path
969 * as with Read Only permission
971 ret = _app2sd_unmount_app_content(application_path);
973 _E("unmount error (%d)", ret);
974 return APP2EXT_ERROR_UNMOUNT;
976 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
978 _E("unable to detach loopback setup for (%s)",
980 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
983 return APP2EXT_SUCCESS;
986 int _app2sd_move_app_to_internal(const char *pkgid, GList* dir_list, uid_t uid)
988 int ret = APP2EXT_SUCCESS;
989 mode_t mode = DIR_PERMS;
990 char temp_dir_path[FILENAME_MAX] = { 0, };
991 char application_mmc_path[FILENAME_MAX] = { 0, };
992 char application_archive_path[FILENAME_MAX] = { 0, };
993 char application_path[FILENAME_MAX] = { 0, };
994 char loopback_device[FILENAME_MAX] = { 0, };
995 char *device_node = NULL;
998 app2ext_dir_details* dir_detail = NULL;
1000 int free_internal_mem = 0;
1001 struct statvfs buf = {0,};
1002 unsigned long long temp = 0;
1003 char err_buf[1024] = {0,};
1005 /* check whether MMC is present or not */
1006 ret = _app2sd_check_mmc_status();
1008 _E("MMC not preset OR Not ready(%d)", ret);
1009 return APP2EXT_ERROR_MMC_STATUS;
1012 if (_is_global(uid)) {
1013 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1014 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1015 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1016 APP2SD_PATH, pkgid);
1018 tzplatform_set_user(uid);
1019 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1020 tzplatform_getenv(TZ_USER_APP), pkgid);
1021 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1022 APP2SD_PATH, tzplatform_getenv(TZ_USER_NAME), pkgid);
1023 tzplatform_reset_user();
1025 _D("application_path = (%s)", application_path);
1026 _D("loopback_device = (%s)", loopback_device);
1028 /* check whether application is in external memory or not */
1029 fp = fopen(loopback_device, "r+");
1031 _E("application (%s) is not installed on SD Card",
1033 return APP2EXT_ERROR_FILE_ABSENT;
1039 memset((void *)&buf, '\0', sizeof(struct statvfs));
1040 ret = statvfs(INTERNAL_STORAGE_PATH, &buf);
1042 temp = (buf.f_bsize * buf.f_bavail) / (1024 * 1024);
1043 free_internal_mem = (int)temp;
1045 _E("unable to get internal storage size");
1046 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1049 fp = fopen(loopback_device, "r+");
1051 _E("app entry is not present in SD card");
1052 return APP2EXT_ERROR_INVALID_PACKAGE;
1056 /* get installed app size*/
1057 temp = _app2sd_calculate_file_size(loopback_device);
1058 reqd_size = (int)((temp) / (1024 * 1024));
1059 _D("reqd size is (%d)", reqd_size);
1061 if (reqd_size == 0) {
1062 _E("app entry is not present in SD Card");
1063 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1066 _D("reqd size: (%d)MB, free internal mem: (%d)MB",
1067 reqd_size, free_internal_mem);
1069 /* if avaialalbe free memory in internal storage is
1070 * less than required size, return error
1072 if (reqd_size > free_internal_mem) {
1073 _E("innsufficient memory in internal storage" \
1074 " for application installation (%d)", ret);
1075 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1078 device_node = _app2sd_find_associated_device_node(loopback_device);
1079 if (NULL == device_node) {
1080 /* do loopback setup */
1081 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1082 loopback_device, uid);
1083 if (device_node == NULL) {
1084 _E("loopback encryption setup failed");
1085 return APP2EXT_ERROR_DO_LOSETUP;
1088 ret = _app2sd_mount_app_content(application_path,
1089 pkgid, device_node, MOUNT_TYPE_RW,
1090 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1093 return APP2EXT_ERROR_MOUNT_PATH;
1096 /* do re-mounting */
1097 ret = _app2sd_mount_app_content(application_path,
1098 pkgid, device_node, MOUNT_TYPE_RW_REMOUNT,
1099 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1101 _E("re-mount failed");
1102 return APP2EXT_ERROR_MOUNT_PATH;
1106 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
1108 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
1110 _D("application_mmc_path = (%s)", application_mmc_path);
1111 _D("application_archive_path = (%s)", application_archive_path);
1113 ret = mkdir(application_archive_path, mode);
1115 if (errno != EEXIST) {
1116 _E("unable to create directory for archiving," \
1117 " error(%d)", errno);
1118 return APP2EXT_ERROR_CREATE_DIRECTORY;
1122 list = g_list_first(dir_list);
1124 dir_detail = (app2ext_dir_details *)list->data;
1125 if (dir_detail && dir_detail->name
1126 && dir_detail->type == APP2EXT_DIR_RO) {
1127 /* archiving code */
1128 memset(temp_dir_path, '\0', FILENAME_MAX);
1129 snprintf(temp_dir_path, FILENAME_MAX,
1130 "%s/%s", application_mmc_path,
1132 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1133 ret = _app2sd_copy_dir(temp_dir_path,
1134 application_archive_path);
1136 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1137 _E("unable to access (%s)",
1141 err_buf, sizeof(err_buf));
1142 _E("unable to copy from (%s) to (%s),"
1145 application_archive_path, err_buf);
1150 /* delete the symbolic link files [bin, lib, res]*/
1151 memset(temp_dir_path, '\0', FILENAME_MAX);
1152 snprintf(temp_dir_path, FILENAME_MAX,
1153 "%s/%s", application_path,
1155 _D("unlink, temp_dir_path(%s)", temp_dir_path);
1156 ret = unlink(temp_dir_path);
1158 if (errno == ENOENT) {
1159 _E("directory (%s) does not exist",
1162 _E("unable to remove the symbolic link file (%s)," \
1163 " it is already unlinked",
1169 /* Copy content to destination */
1170 memset(temp_dir_path, '\0', FILENAME_MAX);
1171 snprintf(temp_dir_path, FILENAME_MAX,
1172 "%s/%s", application_archive_path,
1174 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1175 ret = _app2sd_copy_dir(temp_dir_path, application_path);
1177 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1178 _E("unable to access (%s)",
1182 err_buf, sizeof(err_buf));
1183 _E("unable to copy from (%s) to (%s) " \
1186 application_path, err_buf);
1191 list = g_list_next(list);
1194 _D("copying file completed");
1195 ret = _app2sd_unmount_app_content(application_path);
1197 _E("unable to unmount SD directory for app (%s)",
1199 return APP2EXT_ERROR_UNMOUNT;
1201 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1203 _E("unable to detach loopback setup for (%s)",
1205 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
1207 ret = _app2sd_delete_loopback_device(loopback_device);
1209 _E("unable to delete the loopback device for (%s)",
1211 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1213 ret = _app2sd_delete_directory(application_mmc_path);
1215 _E("unable to delete (%s)", application_mmc_path);
1216 return APP2EXT_ERROR_DELETE_DIRECTORY;
1218 ret = _app2sd_delete_directory(application_archive_path);
1220 _E("unable to delete (%s)", application_archive_path);
1221 return APP2EXT_ERROR_DELETE_DIRECTORY;
1224 return APP2EXT_SUCCESS;
1227 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1228 GList* dir_list, uid_t uid)
1230 int ret = APP2EXT_SUCCESS;
1232 /* Check whether MMC is present or not */
1233 ret = _app2sd_check_mmc_status();
1235 _E("MMC not preset OR Not ready(%d)", ret);
1236 return APP2EXT_ERROR_MMC_STATUS;
1239 switch (move_type) {
1240 case APP2EXT_MOVE_TO_EXT:
1241 ret = _app2sd_move_app_to_external(pkgid, dir_list, uid);
1243 _E("move app to external memory failed(%d)", ret);
1247 case APP2EXT_MOVE_TO_PHONE:
1248 ret = _app2sd_move_app_to_internal(pkgid, dir_list, uid);
1250 _E("move app to internal memory failed(%d)", ret);
1255 _E("invalid argument");
1256 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1262 int _app2sd_copy_ro_content(const char *src, const char *dest, GList* dir_list)
1264 char path[FILENAME_MAX] = { 0, };
1265 int ret = APP2EXT_SUCCESS;
1267 app2ext_dir_details* dir_detail = NULL;
1269 list = g_list_first(dir_list);
1271 dir_detail = (app2ext_dir_details *)list->data;
1272 if (dir_detail && dir_detail->name
1273 && dir_detail->type == APP2EXT_DIR_RO) {
1274 memset((void *)&path, '\0', FILENAME_MAX);
1275 snprintf(path, FILENAME_MAX - 1, "%s/%s", src,
1277 ret = _app2sd_copy_dir(path, dest);
1279 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1280 _E("unable to access (%s)", path);
1282 _E("unable to copy from (%s) " \
1283 "to (%s), errno is (%d)",
1285 return APP2EXT_ERROR_MOVE;
1289 list = g_list_next(list);
1292 return APP2EXT_SUCCESS;
1295 int _app2sd_duplicate_device(const char *pkgid,
1296 const char *loopback_device,
1297 const char *temp_pkgid,
1298 const char *temp_application_path,
1299 const char *temp_loopback_device,
1300 GList* dir_list, char *dev_node, int size,
1306 char *result = NULL;
1308 /* create a new loopback device */
1309 ret = _app2sd_create_loopback_device(temp_pkgid,
1310 temp_loopback_device, (size + PKG_BUF_SIZE));
1312 _E("package already present");
1316 /* perform loopback encryption setup */
1317 dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1318 temp_pkgid, temp_loopback_device, uid);
1320 _E("losetup failed, device node is (%s)", dev_node);
1321 _app2sd_delete_loopback_device(loopback_device);
1322 _E("create ext filesystem failed");
1323 return APP2EXT_ERROR_DO_LOSETUP;
1325 _D("duplicate setup SUCCESS");
1327 /* check whether loopback device is associated with
1328 * device node or not
1330 devi = _app2sd_find_associated_device_node(temp_loopback_device);
1332 _E("finding associated device node failed");
1333 err_res = APP2EXT_ERROR_DO_LOSETUP;
1336 _D("losetup SUCCESS");
1338 /* format the loopback file system */
1339 ret = _app2sd_create_file_system(dev_node);
1341 _E("creating fs failed");
1342 err_res = APP2EXT_ERROR_CREATE_FS;
1345 _D("create filesystem SUCCESS");
1347 /* do mounting for new dev*/
1348 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1349 dev_node, MOUNT_TYPE_RW, dir_list,
1350 APP2SD_PRE_UPGRADE, uid);
1352 _E("remount failed");
1353 err_res = APP2EXT_ERROR_MOUNT_PATH;
1362 return APP2EXT_SUCCESS;
1366 result = _app2sd_detach_loop_device(dev_node);
1371 _app2sd_delete_loopback_device(loopback_device);
1383 int _app2sd_update_loopback_device_size(const char *pkgid,
1384 const char *loopback_device,
1385 const char *application_path,
1386 const char *temp_pkgid,
1387 const char *temp_loopback_device,
1388 const char *temp_application_path,
1389 int size, GList* dir_list,
1393 char *device_node = NULL;
1394 char *old_device_node = NULL;
1396 char application_mmc_path[FILENAME_MAX] = { 0, };
1397 char temp_application_mmc_path[FILENAME_MAX] = { 0, };
1399 ret = _app2sd_duplicate_device(pkgid, loopback_device,
1400 temp_pkgid, temp_application_path, temp_loopback_device,
1401 dir_list, device_node, size, uid);
1403 _E("creating duplicate device failed");
1407 /* get the associated device node for SD card applicatione */
1408 old_device_node = _app2sd_find_associated_device_node(loopback_device);
1409 if (NULL == old_device_node) {
1410 /* do loopback setup */
1411 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1412 loopback_device, uid);
1413 if (old_device_node == NULL) {
1414 _E("loopback encryption setup failed");
1415 err_res = APP2EXT_ERROR_DO_LOSETUP;
1419 ret = _app2sd_mount_app_content(application_path, pkgid,
1420 old_device_node, MOUNT_TYPE_RW, dir_list,
1421 APP2SD_PRE_UPGRADE, uid);
1423 _E("remount failed");
1424 err_res = APP2EXT_ERROR_MOUNT_PATH;
1427 /* do re-mounting */
1428 ret = _app2sd_mount_app_content(application_path, pkgid,
1429 old_device_node, MOUNT_TYPE_RW_REMOUNT, dir_list,
1430 APP2SD_PRE_UPGRADE, uid);
1432 _E("remount failed");
1433 err_res = APP2EXT_ERROR_MOUNT_PATH;
1437 snprintf(application_mmc_path, FILENAME_MAX - 1,
1438 "%s/.mmc", application_path);
1439 snprintf(temp_application_mmc_path, FILENAME_MAX - 1,
1440 "%s/.mmc", temp_application_path);
1442 ret = _app2sd_copy_ro_content(application_mmc_path,
1443 temp_application_mmc_path, dir_list);
1445 _E("copy ro content failed");
1449 ret = _app2sd_unmount_app_content(application_path);
1451 _E("unable to unmount the SD application");
1452 err_res = APP2EXT_ERROR_UNMOUNT;
1455 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1457 _E("unable to remove loopback setup");
1458 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1461 ret = _app2sd_unmount_app_content(temp_application_path);
1463 _E("unable to unmount the SD application");
1464 err_res = APP2EXT_ERROR_UNMOUNT;
1468 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1470 _E("unable to remove loopback setup");
1471 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1475 ret = _app2sd_delete_directory(loopback_device);
1477 _E("unable to delete (%s)", loopback_device);
1478 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1482 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1484 _E("unable to rename (%s)", temp_loopback_device);
1485 err_res = APP2EXT_ERROR_MOVE;
1489 ret = _app2sd_delete_directory(temp_application_path);
1491 _E("unable to delete (%s)", temp_application_path);
1492 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1496 return APP2EXT_SUCCESS;
1499 if (old_device_node) {
1500 free(old_device_node);
1501 old_device_node = NULL;
1504 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1506 _E("unable to remove loopback setup");
1507 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1513 void _app2sd_make_result_info_file(char *pkgid, int size, uid_t uid)
1518 char buf[FILENAME_MAX] = {0};
1519 const char* app_info_label = "*";
1520 char info_file[FILENAME_MAX] = {'\0', };
1522 struct passwd *pwd_result;
1527 snprintf(info_file, FILENAME_MAX - 1, "/tmp/%s", pkgid);
1528 _D("file path = %s", info_file);
1530 file = fopen(info_file, "w");
1532 _E("couldn't open the file (%s)", info_file);
1536 snprintf(buf, FILENAME_MAX - 1, "%d\n", size);
1537 fwrite(buf, 1, strlen(buf), file);
1544 if(lsetxattr(info_file, "security.SMACK64", app_info_label, strlen(app_info_label), 0)) {
1545 _E("error(%d) in setting smack label", errno);
1548 ret = chmod(info_file, 0755);
1553 memset(buf, '\0', FILENAME_MAX);
1554 ret = getpwuid_r(uid, &pwd, buf, FILENAME_MAX, &pwd_result);
1555 if (ret != 0 || pwd_result == NULL) {
1556 _E("get uid failed(%d)", ret);
1559 ret = chown(info_file, uid, pwd.pw_gid);