4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Garima Shrivastava<garima.s@samsung.com>
7 * Jyotsna Dhumale <jyotsna.a@samsung.com>
8 * Venkatesha Sarpangala <sarpangala.v@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
25 #include <openssl/sha.h>
29 #include "app2sd_internals.h"
31 static int _app2sd_setup_path(const char* path, const char *label, uid_t uid)
33 int ret = APP2EXT_SUCCESS;
35 struct passwd *pwd_result;
36 char buf[1024] = { 0, };
39 fd = open(path, O_RDONLY);
41 _E("can't open path(%s)", path);
42 return APP2EXT_ERROR_OPEN_DIR;
44 ret = fchmod(fd, 0755);
46 _E("change file permission error");
48 return APP2EXT_ERROR_ACCESS_FILE;
52 ret = lsetxattr(path, "security.SMACK64TRANSMUTE", "TRUE", 4, 0);
54 _E("set transmute error");
55 return APP2EXT_ERROR_ACCESS_FILE;
57 ret = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
59 _E("set label(%s) error", label);
60 return APP2EXT_ERROR_ACCESS_FILE;
63 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
64 if (ret != 0 || pwd_result == NULL) {
65 _E("get uid failed(%d)", ret);
66 return APP2EXT_ERROR_ACCESS_FILE;
69 _D("uid(%d), gid(%d)", uid, pwd.pw_gid);
70 ret = chown(path, uid, pwd.pw_gid);
72 _E("change file owner error");
73 return APP2EXT_ERROR_ACCESS_FILE;
79 static int _app2sd_apply_app_smack(const char *application_path,
80 const char *pkgid, GList* dir_list, uid_t uid)
82 int ret = APP2EXT_SUCCESS;
84 app2ext_dir_details* dir_detail = NULL;
85 char temp_dir_path[FILENAME_MAX] = { 0, };
86 char label[FILENAME_MAX] = { 0, };
88 snprintf(label, FILENAME_MAX, "User::Pkg::%s::RO", pkgid);
89 list = g_list_first(dir_list);
91 dir_detail = (app2ext_dir_details *)list->data;
92 if (dir_detail && dir_detail->name
93 && dir_detail->type == APP2EXT_DIR_RO) {
94 memset(temp_dir_path, '\0', FILENAME_MAX);
95 snprintf(temp_dir_path, FILENAME_MAX,
96 "%s/%s", application_path,
98 _D("set label(%s) to path(%s)",
99 label, temp_dir_path);
100 ret = _app2sd_setup_path(temp_dir_path, /* label */ "*", uid);
102 _E("unable to smack (%s)", label);
103 return APP2EXT_ERROR_MOVE;
106 list = g_list_next(list);
109 return APP2EXT_SUCCESS;
112 char *_app2sd_find_associated_device_node(const char *loopback_device)
114 char *ret_result = NULL;
117 char dev[FILENAME_MAX] = { 0, };
118 char *devnode = NULL;
120 result = (char *)_app2sd_find_associated_device(loopback_device);
121 if (result == NULL) {
122 _D("there is no the associated file (%s)", loopback_device);
126 /* process the string*/
127 snprintf(dev, FILENAME_MAX - 1, "%s", result);
129 if (strstr(dev, "dev") == NULL) {
130 _E("unable to find the associated file");
134 char *saveptr = NULL;
135 ret_result = strtok_r(dev, delims, &saveptr);
137 devnode = strdup(ret_result);
145 char *_app2sd_create_loopdevice_node(void)
147 char *ret_result = NULL;
148 mode_t mode = DIR_PERMS;
150 int ret = APP2EXT_SUCCESS;
154 result = (char *)_app2sd_find_free_device();
155 _D("find_free_device(%s)", result);
157 /* validate the result */
158 if (result == NULL || strstr(result, "/dev") == NULL) {
159 _D("no device found, creating device node");
166 char dev_path[BUF_SIZE] = { 0, };
167 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
168 while ((fp = fopen(dev_path, "r+")) != NULL) {
170 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
171 _D("next dev path for checking is (%s)",
175 _D("device node candidate is (%s)", dev_path);
177 dev_node = makedev(DEV_MAJOR, count);
178 ret = mknod(dev_path, S_IFBLK | mode, dev_node);
180 _E("error while creating the device node: errno is (%d)",
184 ret_result = (char *)malloc(strlen(dev_path) + 1);
185 if (ret_result == NULL) {
186 _E("unable to allocate memory");
189 memset(ret_result, '\0', strlen(dev_path) + 1);
190 memcpy(ret_result, dev_path, strlen(dev_path));
192 ret_result = (char *)malloc(strlen(result) + 1);
193 if (ret_result == NULL) {
199 memset(ret_result, '\0', strlen(result) + 1);
200 if (strlen(result) > 0) {
201 memcpy(ret_result, result, strlen(result) - 1);
210 char *_app2sd_do_loopback_encryption_setup(const char *pkgid,
211 const char *loopback_device, uid_t uid)
213 int ret = APP2EXT_SUCCESS;
216 char *device_node = NULL;
219 _E("invalid argument");
223 /* get password for loopback encryption */
224 ret = _app2sd_initialize_db();
226 _E("app2sd db initialize failed");
230 if ((passwd = _app2sd_get_password_from_db(pkgid)) == NULL) {
231 passwd = (char *)_app2sd_generate_password(pkgid);
232 if (NULL == passwd) {
233 _E("unable to generate password");
236 if ((ret = _app2sd_set_password_in_db(pkgid,
238 _E("unable to save password");
246 /* get free device node*/
247 device_node = _app2sd_create_loopdevice_node();
248 if (NULL == device_node) {
251 _E("unable to find free loopback node");
255 _D("device_node (%s)", device_node);
257 result = (char *)_app2sd_encrypt_device(device_node,
258 loopback_device, passwd);
259 if (result == NULL) {
260 _E("encryption failed");
265 _D("result (%s)", result);
274 char *_app2sd_do_loopback_duplicate_encryption_setup(const char *pkgid,
275 const char *temp_pkgid, const char *temp_loopback_device,
278 int ret = APP2EXT_SUCCESS;
281 char *device_node = NULL;
283 if (pkgid == NULL || temp_pkgid == NULL ||
284 temp_loopback_device == NULL) {
285 _E("invalid argument");
289 /* get password for loopback encryption */
290 ret = _app2sd_initialize_db();
292 _E("app2sd db initialize failed");
296 if ((passwd = _app2sd_get_password_from_db(pkgid)) == NULL) {
297 passwd = (char *)_app2sd_generate_password(pkgid);
298 if (NULL == passwd) {
299 _E("unable to generate password");
302 if ((ret = _app2sd_set_password_in_db(pkgid,
304 _E("unable to save password");
313 /* get free device node*/
314 device_node = _app2sd_create_loopdevice_node();
315 if (NULL == device_node) {
318 _E("unable to find free loopback node");
321 result = (char *)_app2sd_encrypt_device(device_node,
322 temp_loopback_device, passwd);
323 if (result == NULL) {
324 _E("encryption failed");
329 if (strlen(result) == 0) {
336 _E("error is (%s)", result);
348 int _app2sd_remove_loopback_encryption_setup(const char *loopback_device)
350 int ret = APP2EXT_SUCCESS;
352 char *dev_node = NULL;
354 if ((dev_node = _app2sd_find_associated_device_node(loopback_device))
356 _E("Unable to find the association");
357 ret = APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE;
360 result = (char *)_app2sd_detach_loop_device(dev_node);
361 if (result == NULL) {
362 _E("error in detaching");
363 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
377 int _app2sd_remove_all_loopback_encryption_setups(const char *loopback_device)
379 int ret = APP2EXT_SUCCESS;
381 char *dev_node = NULL;
384 _app2sd_find_associated_device_node(loopback_device))
386 _E("finish to find the association");
387 ret = APP2EXT_SUCCESS;
391 _D("find node (%s)", dev_node);
393 result = (char *)_app2sd_detach_loop_device(dev_node);
394 if (result == NULL) {
395 _E("error in detaching");
396 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
411 int _app2sd_create_loopback_device(const char *pkgid,
412 const char *loopback_device, int size)
414 int ret = APP2EXT_SUCCESS;
415 char command[FILENAME_MAX] = { 0, };
416 char buff[BUF_SIZE] = { 0, };
419 if (NULL == pkgid || size <= 0) {
420 _E("invalid argument");
421 return APP2EXT_ERROR_INVALID_ARGUMENTS;
423 snprintf(command, FILENAME_MAX - 1, "of=%s", loopback_device);
424 snprintf(buff, BUF_SIZE - 1, "count=%d", size);
426 const char *argv1[] =
427 { "dd", "if=/dev/zero", command, "bs=1M", buff, NULL };
429 if ((fp = fopen(loopback_device, "r+")) != NULL) {
430 _E("encrypted file already exists (%s)",
433 return APP2EXT_ERROR_PKG_EXISTS;
436 ret = _xsystem(argv1);
438 _E("command (%s) failed", command);
443 int _app2sd_delete_loopback_device(const char *loopback_device)
445 int ret = APP2EXT_SUCCESS;
447 ret = unlink(loopback_device);
449 if (errno == ENOENT) {
450 _E("unable to access file (%s)", loopback_device);
452 _E("unable to delete (%s)", loopback_device);
453 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
460 int _app2sd_create_file_system(const char *device_path)
462 int ret = APP2EXT_SUCCESS;
464 char err_buf[1024] = {0,};
466 if (device_path == NULL) {
468 return APP2EXT_ERROR_INVALID_ARGUMENTS;
471 /* Format the filesystem [create a filesystem]*/
472 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
473 fp = fopen(device_path, "r+");
475 strerror_r(errno, err_buf, sizeof(err_buf));
476 _E("unable to access (%s) error is (%d, %s)",
477 device_path, errno, err_buf);
478 return APP2EXT_ERROR_ACCESS_FILE;
482 ret = _xsystem(argv);
484 strerror_r(errno, err_buf, sizeof(err_buf));
485 _E("creating file system failed, error is (%s)",
487 return APP2EXT_ERROR_CREATE_FS;
492 static int _app2sd_create_dir_with_link(const char *application_path,
493 const char *pkgid, const char *dir_name, uid_t uid)
495 mode_t mode = DIR_PERMS;
496 int ret = APP2EXT_SUCCESS;
497 char application_dir_mmc_path[FILENAME_MAX] = { 0, };
498 char application_dir_path[FILENAME_MAX] = { 0, };
499 char label[FILENAME_MAX] = { 0, };
501 snprintf(application_dir_mmc_path, FILENAME_MAX - 1, "%s/.mmc/%s",
502 application_path, dir_name);
503 snprintf(application_dir_path, FILENAME_MAX, "%s/%s",
504 application_path, dir_name);
505 snprintf(label, FILENAME_MAX, "User::Pkg::%s::RO", pkgid);
507 ret = mkdir(application_dir_mmc_path, mode);
509 if (errno != EEXIST) {
510 _E("create directory failed," \
511 " error no is (%d)", errno);
512 return APP2EXT_ERROR_CREATE_DIRECTORY;
516 if ((ret = symlink(application_dir_mmc_path,
517 application_dir_path)) < 0) {
518 if (errno == EEXIST) {
519 _D("file with symlink name present (%s)",
520 application_dir_path);
522 _E("symbolic link creation "
523 "failed, error no is (%d)", errno);
524 return APP2EXT_ERROR_CREATE_SYMLINK;
528 ret = _app2sd_setup_path(application_dir_path, /* label */ "*", uid);
530 _E ("unable to smack (%s)", application_dir_path);
531 return APP2EXT_ERROR_MOVE;
534 ret = _app2sd_setup_path(application_dir_mmc_path, /* label */ "*", uid);
536 _E ("unable to smack (%s)", application_dir_mmc_path);
537 return APP2EXT_ERROR_MOVE;
543 static int _app2sd_create_directory_entry(const char *application_path,
544 const char *pkgid, GList* dir_list, uid_t uid)
546 int ret = APP2EXT_SUCCESS;
548 app2ext_dir_details* dir_detail = NULL;
550 list = g_list_first(dir_list);
552 dir_detail = (app2ext_dir_details *)list->data;
553 if (dir_detail && dir_detail->name
554 && dir_detail->type == APP2EXT_DIR_RO) {
555 ret = _app2sd_create_dir_with_link(application_path,
556 pkgid, dir_detail->name, uid);
561 list = g_list_next(list);
563 return APP2EXT_SUCCESS;
566 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
567 const char *dev, int mount_type, GList* dir_list,
568 app2sd_cmd cmd, uid_t uid)
570 int ret = APP2EXT_SUCCESS;
571 mode_t mode = DIR_PERMS;
572 char application_mmc_path[FILENAME_MAX] = { 0, };
573 char temp_path[FILENAME_MAX] = { 0, };
574 char label[FILENAME_MAX] = { 0, };
575 struct timespec time = {
577 .tv_nsec = 1000 * 1000 * 200
581 _E("input param is NULL (%s)",
583 return APP2EXT_ERROR_INVALID_ARGUMENTS;
586 ret = mkdir(application_path, mode);
588 if (errno != EEXIST) {
589 _E("create directory failed," \
590 " error no is (%d)", errno);
591 return APP2EXT_ERROR_CREATE_DIRECTORY;
594 ret = _app2sd_setup_path(application_path, "*", uid);
596 _E ("unable to smack (%s)", application_path);
597 return APP2EXT_ERROR_ACCESS_FILE;
601 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
603 ret = mkdir(application_mmc_path, mode);
605 if (errno != EEXIST) {
606 _E("create directory failed," \
607 " error no is (%d)", errno);
608 return APP2EXT_ERROR_CREATE_DIRECTORY;
611 snprintf(label, FILENAME_MAX, "User::Pkg::%s::RO", pkgid);
612 ret = _app2sd_setup_path(application_mmc_path, /* label */ "*", uid);
614 _E ("unable to smack (%s)", application_mmc_path);
615 return APP2EXT_ERROR_ACCESS_FILE;
619 nanosleep(&time, NULL); /* 200ms sleep */
620 _D("give a delay for mount");
622 switch (mount_type) {
624 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
625 MS_MGC_VAL | MS_RDONLY | MS_NOSUID, NULL)) < 0) {
626 _E("read only mount failed, " \
628 "dev is (%s) path is (%s)",
629 errno, dev, application_mmc_path);
630 ret = APP2EXT_ERROR_MOUNT;
634 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
635 MS_MGC_VAL | MS_NOSUID, NULL)) < 0) {
636 _E("read write mount failed, " \
637 "errono is (%d)", errno);
638 ret = APP2EXT_ERROR_MOUNT;
641 case MOUNT_TYPE_RW_NOEXEC:
642 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
643 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID, NULL)) < 0) {
644 _E("rwnx mount failed " \
645 "errono is (%d)", errno);
646 ret = APP2EXT_ERROR_MOUNT;
649 case MOUNT_TYPE_RD_REMOUNT:
650 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
651 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT | MS_NOSUID,
653 _E("read remount failed "
654 "errono is (%d)", errno);
655 ret = APP2EXT_ERROR_MOUNT;
658 case MOUNT_TYPE_RW_REMOUNT:
659 if ((ret = mount(dev, application_mmc_path, FS_TYPE,
660 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID, NULL)) < 0) {
661 _E("read write remount failed "
662 "erro no is (%d)", errno);
663 ret = APP2EXT_ERROR_MOUNT;
667 _E("invalid mount type");
671 if (cmd == APP2SD_PRE_UNINSTALL || cmd == APP2SD_PRE_UPGRADE) {
672 /* delete lost+found dir */
673 snprintf(temp_path, FILENAME_MAX - 1, "%s/lost+found",
674 application_mmc_path);
675 ret = _app2sd_delete_directory(temp_path);
676 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
677 _E("unable to delete (%s)", temp_path);
678 return APP2EXT_ERROR_DELETE_DIRECTORY;
682 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
683 cmd == APP2SD_PRE_UPGRADE) {
684 ret = _app2sd_create_directory_entry(application_path,
685 pkgid, dir_list, uid);
691 int _app2sd_unmount_app_content(const char *application_path)
693 int ret = APP2EXT_SUCCESS;
694 char application_dir_mmc_path[FILENAME_MAX] = { 0, };
695 char err_buf[1024] = {0,};
697 snprintf(application_dir_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
699 if ((ret = umount(application_dir_mmc_path)) < 0) {
700 strerror_r(errno, err_buf, sizeof(err_buf));
701 _E("unable to umount the dir, ret(%d) error(%d, %s)",
702 ret, errno, err_buf);
708 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
710 int ret = APP2EXT_SUCCESS;
712 ret = _app2sd_copy_dir(src_path, arch_path);
713 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
714 char err_buf[1024] = {0,};
715 strerror_r(errno, err_buf, sizeof(err_buf));
716 _E("unable to copy from (%s) to (%s), err is (%s)",
717 src_path, arch_path, err_buf);
718 return APP2EXT_ERROR_MOVE;
721 ret = _app2sd_delete_directory((char *)src_path);
722 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
723 _E("unable to delete (%s)", src_path);
724 return APP2EXT_ERROR_DELETE_DIRECTORY;
730 int _app2sd_move_app_to_external(const char *pkgid, GList* dir_list, uid_t uid)
732 int ret = APP2EXT_SUCCESS;
733 char temp_dir_path[FILENAME_MAX] = { 0, };
734 char application_mmc_path[FILENAME_MAX] = { 0, };
735 char application_archive_path[FILENAME_MAX] = { 0, };
736 char application_path[FILENAME_MAX] = { 0, };
737 char loopback_device[FILENAME_MAX] = { 0, };
738 unsigned long long total_size = 0;
740 int reqd_disk_size = 0;
741 char *device_node = NULL;
743 mode_t mode = DIR_PERMS;
744 int free_mmc_mem = 0;
747 app2ext_dir_details* dir_detail = NULL;
748 char err_buf[1024] = {0,};
749 char *encoded_id = NULL;
751 /* check whether MMC is present or not */
752 ret = _app2sd_check_mmc_status();
754 _E("MMC not preset OR Not ready(%d)", ret);
755 return APP2EXT_ERROR_MMC_STATUS;
758 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
759 if (encoded_id == NULL) {
760 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
762 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
763 APP2SD_PATH, encoded_id);
765 if (_is_global(uid)) {
766 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
767 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
769 tzplatform_set_user(uid);
770 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
771 tzplatform_getenv(TZ_USER_APP), pkgid);
772 tzplatform_reset_user();
775 /* check whether application is in external memory or not */
776 fp = fopen(loopback_device, "r+");
778 _W("Already %s entry is present in the SD Card, " \
779 "delete entry and go on without return", pkgid);
781 app2sd_usr_force_clean(pkgid, uid);
784 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
786 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
788 _D("application_mmc_path = (%s)", application_mmc_path);
789 _D("application_archive_path = (%s)", application_archive_path);
791 ret = mkdir(application_archive_path, mode);
793 if (errno != EEXIST) {
794 _E("unable to create directory for archiving," \
795 " error(%d)", errno);
796 return APP2EXT_ERROR_CREATE_DIRECTORY;
800 list = g_list_first(dir_list);
802 dir_detail = (app2ext_dir_details *)list->data;
803 if (dir_detail && dir_detail->name
804 && dir_detail->type == APP2EXT_DIR_RO) {
805 memset(temp_dir_path, '\0', FILENAME_MAX);
806 snprintf(temp_dir_path, FILENAME_MAX,
807 "%s/%s", application_path,
809 _D("cal size of app dirs, temp_dir_path(%s)",
812 _app2sd_calculate_dir_size(temp_dir_path);
814 list = g_list_next(list);
817 reqd_size = ((total_size) / ( 1024 * 1024)) + 2;
818 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
820 /* find avialable free memory in the MMC card */
821 ret = _app2sd_get_available_free_memory(MMC_PATH, &free_mmc_mem);
823 _E("unable to get available free memory in MMC (%d)", ret);
824 return APP2EXT_ERROR_MMC_STATUS;
826 /* if avaialalbe free memory in MMC is less than
827 * required size + 5MB, return error
829 if (reqd_disk_size > free_mmc_mem) {
830 _E("insufficient memory in MMC for application installation (%d)",
832 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
834 /* create a loopback device */
835 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
836 (reqd_disk_size + PKG_BUF_SIZE));
838 _E("loopback node creation failed");
841 /* perform loopback encryption setup */
842 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
843 loopback_device, uid);
845 _E("loopback encryption setup failed");
846 return APP2EXT_ERROR_DO_LOSETUP;
848 _D("device_node (%s)", device_node);
849 /* check whether loopback device is associated with device node or not */
850 devi = _app2sd_find_associated_device_node(loopback_device);
852 _E("finding associated device node failed");
853 return APP2EXT_ERROR_DO_LOSETUP;
858 /* format the loopback file system */
859 ret = _app2sd_create_file_system(device_node);
861 _E("create ext4 filesystem failed");
862 return APP2EXT_ERROR_CREATE_FS;
865 list = g_list_first(dir_list);
867 dir_detail = (app2ext_dir_details *)list->data;
868 if (dir_detail && dir_detail->name
869 && dir_detail->type == APP2EXT_DIR_RO) {
870 memset(temp_dir_path, '\0', FILENAME_MAX);
871 snprintf(temp_dir_path, FILENAME_MAX,
872 "%s/%s", application_path,
874 _D("app2archive, temp_dir_path(%s)",
876 ret = _app2sd_move_to_archive(temp_dir_path,
877 application_archive_path);
879 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
880 _E("unable to access (%s)",
883 _E("unable to copy from (%s) to (%s)",
885 application_archive_path);
890 list = g_list_next(list);
893 /* mount the loopback encrypted pseudo device on application installation path
894 * as with Read Write permission
896 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
897 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
903 list = g_list_first(dir_list);
905 dir_detail = (app2ext_dir_details *)list->data;
906 if (dir_detail && dir_detail->name
907 && dir_detail->type == APP2EXT_DIR_RO) {
908 memset(temp_dir_path, '\0', FILENAME_MAX);
909 snprintf(temp_dir_path, FILENAME_MAX,
910 "%s/%s", application_archive_path,
912 _D("archive2mmc, temp_dir_path(%s)",
914 ret = _app2sd_copy_dir(temp_dir_path,
915 application_mmc_path);
917 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
918 _E("unable to access (%s)",
922 err_buf, sizeof(err_buf));
923 _E("unable to copy from (%s) to (%s)," \
926 application_mmc_path, err_buf);
930 ret = _app2sd_delete_directory(temp_dir_path);
932 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
933 _E("unable to access (%s)",
936 _E("unable to delete (%s)",
942 list = g_list_next(list);
945 ret = _app2sd_delete_directory(application_archive_path);
947 _E("unable to delete (%s)", application_archive_path);
948 return APP2EXT_ERROR_DELETE_DIRECTORY;
951 ret = _app2sd_apply_app_smack(application_path, pkgid, dir_list, uid);
953 _E("unable to apply app smack");
954 return APP2EXT_ERROR_MOVE;
957 /* re-mount the loopback encrypted pseudo device on application installation path
958 * as with Read Only permission
960 ret = _app2sd_unmount_app_content(application_path);
962 _E("unmount error (%d)", ret);
963 return APP2EXT_ERROR_UNMOUNT;
965 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
967 _E("unable to detach loopback setup for (%s)",
969 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
972 return APP2EXT_SUCCESS;
975 int _app2sd_move_app_to_internal(const char *pkgid, GList* dir_list, uid_t uid)
977 int ret = APP2EXT_SUCCESS;
978 mode_t mode = DIR_PERMS;
979 char temp_dir_path[FILENAME_MAX] = { 0, };
980 char application_mmc_path[FILENAME_MAX] = { 0, };
981 char application_archive_path[FILENAME_MAX] = { 0, };
982 char application_path[FILENAME_MAX] = { 0, };
983 char loopback_device[FILENAME_MAX] = { 0, };
984 char *device_node = NULL;
987 app2ext_dir_details* dir_detail = NULL;
989 int free_internal_mem = 0;
990 struct statvfs buf = {0,};
991 unsigned long long temp = 0;
992 char err_buf[1024] = {0,};
993 char *encoded_id = NULL;
995 /* check whether MMC is present or not */
996 ret = _app2sd_check_mmc_status();
998 _E("MMC not preset OR Not ready(%d)", ret);
999 return APP2EXT_ERROR_MMC_STATUS;
1002 encoded_id = _app2sd_get_encoded_name(pkgid, uid);
1003 if (encoded_id == NULL) {
1004 return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
1006 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1007 APP2SD_PATH, encoded_id);
1009 if (_is_global(uid)) {
1010 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1011 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1013 tzplatform_set_user(uid);
1014 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1015 tzplatform_getenv(TZ_USER_APP), pkgid);
1016 tzplatform_reset_user();
1019 /* check whether application is in external memory or not */
1020 fp = fopen(loopback_device, "r+");
1022 _E("application (%s) is not installed on SD Card",
1024 return APP2EXT_ERROR_FILE_ABSENT;
1030 memset((void *)&buf, '\0', sizeof(struct statvfs));
1031 ret = statvfs(INTERNAL_STORAGE_PATH, &buf);
1033 temp = (buf.f_bsize * buf.f_bavail) / (1024 * 1024);
1034 free_internal_mem = (int)temp;
1036 _E("unable to get internal storage size");
1037 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1040 fp = fopen(loopback_device, "r+");
1042 _E("app entry is not present in SD card");
1043 return APP2EXT_ERROR_INVALID_PACKAGE;
1047 /* get installed app size*/
1048 temp = _app2sd_calculate_file_size(loopback_device);
1049 reqd_size = (int)((temp) / (1024 * 1024));
1050 _D("reqd size is (%d)", reqd_size);
1052 if (reqd_size == 0) {
1053 _E("app entry is not present in SD Card");
1054 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1057 _D("reqd size: (%d)MB, free internal mem: (%d)MB",
1058 reqd_size, free_internal_mem);
1060 /* if avaialalbe free memory in internal storage is
1061 * less than required size, return error
1063 if (reqd_size > free_internal_mem) {
1064 _E("innsufficient memory in internal storage" \
1065 " for application installation (%d)", ret);
1066 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1069 device_node = _app2sd_find_associated_device_node(loopback_device);
1070 if (NULL == device_node) {
1071 /* do loopback setup */
1072 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1073 loopback_device, uid);
1074 if (device_node == NULL) {
1075 _E("loopback encryption setup failed");
1076 return APP2EXT_ERROR_DO_LOSETUP;
1079 ret = _app2sd_mount_app_content(application_path,
1080 pkgid, device_node, MOUNT_TYPE_RW,
1081 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1084 return APP2EXT_ERROR_MOUNT_PATH;
1087 /* do re-mounting */
1088 ret = _app2sd_mount_app_content(application_path,
1089 pkgid, device_node, MOUNT_TYPE_RW_REMOUNT,
1090 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1092 _E("re-mount failed");
1093 return APP2EXT_ERROR_MOUNT_PATH;
1097 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
1099 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
1101 _D("application_mmc_path = (%s)", application_mmc_path);
1102 _D("application_archive_path = (%s)", application_archive_path);
1104 ret = mkdir(application_archive_path, mode);
1106 if (errno != EEXIST) {
1107 _E("unable to create directory for archiving," \
1108 " error(%d)", errno);
1109 return APP2EXT_ERROR_CREATE_DIRECTORY;
1113 list = g_list_first(dir_list);
1115 dir_detail = (app2ext_dir_details *)list->data;
1116 if (dir_detail && dir_detail->name
1117 && dir_detail->type == APP2EXT_DIR_RO) {
1118 /* archiving code */
1119 memset(temp_dir_path, '\0', FILENAME_MAX);
1120 snprintf(temp_dir_path, FILENAME_MAX,
1121 "%s/%s", application_mmc_path,
1123 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1124 ret = _app2sd_copy_dir(temp_dir_path,
1125 application_archive_path);
1127 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1128 _E("unable to access (%s)",
1132 err_buf, sizeof(err_buf));
1133 _E("unable to copy from (%s) to (%s),"
1136 application_archive_path, err_buf);
1141 /* delete the symbolic link files [bin, lib, res]*/
1142 memset(temp_dir_path, '\0', FILENAME_MAX);
1143 snprintf(temp_dir_path, FILENAME_MAX,
1144 "%s/%s", application_path,
1146 _D("unlink, temp_dir_path(%s)", temp_dir_path);
1147 ret = unlink(temp_dir_path);
1149 if (errno == ENOENT) {
1150 _E("directory (%s) does not exist",
1153 _E("unable to remove the symbolic link file (%s)," \
1154 " it is already unlinked",
1160 /* Copy content to destination */
1161 memset(temp_dir_path, '\0', FILENAME_MAX);
1162 snprintf(temp_dir_path, FILENAME_MAX,
1163 "%s/%s", application_archive_path,
1165 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1166 ret = _app2sd_copy_dir(temp_dir_path, application_path);
1168 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1169 _E("unable to access (%s)",
1173 err_buf, sizeof(err_buf));
1174 _E("unable to copy from (%s) to (%s) " \
1177 application_path, err_buf);
1182 list = g_list_next(list);
1185 _D("copying file completed");
1186 ret = _app2sd_unmount_app_content(application_path);
1188 _E("unable to unmount SD directory for app (%s)",
1190 return APP2EXT_ERROR_UNMOUNT;
1192 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1194 _E("unable to detach loopback setup for (%s)",
1196 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
1198 ret = _app2sd_delete_loopback_device(loopback_device);
1200 _E("unable to delete the loopback device for (%s)",
1202 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1204 ret = _app2sd_delete_directory(application_mmc_path);
1206 _E("unable to delete (%s)", application_mmc_path);
1207 return APP2EXT_ERROR_DELETE_DIRECTORY;
1209 ret = _app2sd_delete_directory(application_archive_path);
1211 _E("unable to delete (%s)", application_archive_path);
1212 return APP2EXT_ERROR_DELETE_DIRECTORY;
1215 return APP2EXT_SUCCESS;
1218 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1219 GList* dir_list, uid_t uid)
1221 int ret = APP2EXT_SUCCESS;
1223 /* Check whether MMC is present or not */
1224 ret = _app2sd_check_mmc_status();
1226 _E("MMC not preset OR Not ready(%d)", ret);
1227 return APP2EXT_ERROR_MMC_STATUS;
1230 switch (move_type) {
1231 case APP2EXT_MOVE_TO_EXT:
1232 ret = _app2sd_move_app_to_external(pkgid, dir_list, uid);
1234 _E("move app to external memory failed(%d)", ret);
1238 case APP2EXT_MOVE_TO_PHONE:
1239 ret = _app2sd_move_app_to_internal(pkgid, dir_list, uid);
1241 _E("move app to internal memory failed(%d)", ret);
1246 _E("invalid argument");
1247 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1253 int _app2sd_copy_ro_content(const char *src, const char *dest, GList* dir_list)
1255 char path[FILENAME_MAX] = { 0, };
1256 int ret = APP2EXT_SUCCESS;
1258 app2ext_dir_details* dir_detail = NULL;
1260 list = g_list_first(dir_list);
1262 dir_detail = (app2ext_dir_details *)list->data;
1263 if (dir_detail && dir_detail->name
1264 && dir_detail->type == APP2EXT_DIR_RO) {
1265 memset((void *)&path, '\0', FILENAME_MAX);
1266 snprintf(path, FILENAME_MAX - 1, "%s/%s", src,
1268 ret = _app2sd_copy_dir(path, dest);
1270 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1271 _E("unable to access (%s)", path);
1273 _E("unable to copy from (%s) " \
1274 "to (%s), errno is (%d)",
1276 return APP2EXT_ERROR_MOVE;
1280 list = g_list_next(list);
1283 return APP2EXT_SUCCESS;
1286 int _app2sd_duplicate_device(const char *pkgid,
1287 const char *loopback_device,
1288 const char *temp_pkgid,
1289 const char *temp_application_path,
1290 const char *temp_loopback_device,
1291 GList* dir_list, char *dev_node, int size,
1297 char *result = NULL;
1299 /* create a new loopback device */
1300 ret = _app2sd_create_loopback_device(temp_pkgid,
1301 temp_loopback_device, (size + PKG_BUF_SIZE));
1303 _E("package already present");
1307 /* perform loopback encryption setup */
1308 dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1309 temp_pkgid, temp_loopback_device, uid);
1311 _E("losetup failed, device node is (%s)", dev_node);
1312 _app2sd_delete_loopback_device(loopback_device);
1313 _E("create ext filesystem failed");
1314 return APP2EXT_ERROR_DO_LOSETUP;
1316 _D("duplicate setup SUCCESS");
1318 /* check whether loopback device is associated with
1319 * device node or not
1321 devi = _app2sd_find_associated_device_node(temp_loopback_device);
1323 _E("finding associated device node failed");
1324 err_res = APP2EXT_ERROR_DO_LOSETUP;
1327 _D("losetup SUCCESS");
1329 /* format the loopback file system */
1330 ret = _app2sd_create_file_system(dev_node);
1332 _E("creating fs failed");
1333 err_res = APP2EXT_ERROR_CREATE_FS;
1336 _D("create filesystem SUCCESS");
1338 /* do mounting for new dev*/
1339 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1340 dev_node, MOUNT_TYPE_RW, dir_list,
1341 APP2SD_PRE_UPGRADE, uid);
1343 _E("remount failed");
1344 err_res = APP2EXT_ERROR_MOUNT_PATH;
1353 return APP2EXT_SUCCESS;
1357 result = _app2sd_detach_loop_device(dev_node);
1362 _app2sd_delete_loopback_device(loopback_device);
1374 int _app2sd_update_loopback_device_size(const char *pkgid,
1375 const char *loopback_device,
1376 const char *application_path,
1377 const char *temp_pkgid,
1378 const char *temp_loopback_device,
1379 const char *temp_application_path,
1380 int size, GList* dir_list,
1384 char *device_node = NULL;
1385 char *old_device_node = NULL;
1387 char application_mmc_path[FILENAME_MAX] = { 0, };
1388 char temp_application_mmc_path[FILENAME_MAX] = { 0, };
1390 ret = _app2sd_duplicate_device(pkgid, loopback_device,
1391 temp_pkgid, temp_application_path, temp_loopback_device,
1392 dir_list, device_node, size, uid);
1394 _E("creating duplicate device failed");
1398 /* get the associated device node for SD card applicatione */
1399 old_device_node = _app2sd_find_associated_device_node(loopback_device);
1400 if (NULL == old_device_node) {
1401 /* do loopback setup */
1402 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1403 loopback_device, uid);
1404 if (old_device_node == NULL) {
1405 _E("loopback encryption setup failed");
1406 err_res = APP2EXT_ERROR_DO_LOSETUP;
1410 ret = _app2sd_mount_app_content(application_path, pkgid,
1411 old_device_node, MOUNT_TYPE_RW, dir_list,
1412 APP2SD_PRE_UPGRADE, uid);
1414 _E("remount failed");
1415 err_res = APP2EXT_ERROR_MOUNT_PATH;
1418 /* do re-mounting */
1419 ret = _app2sd_mount_app_content(application_path, pkgid,
1420 old_device_node, MOUNT_TYPE_RW_REMOUNT, dir_list,
1421 APP2SD_PRE_UPGRADE, uid);
1423 _E("remount failed");
1424 err_res = APP2EXT_ERROR_MOUNT_PATH;
1428 snprintf(application_mmc_path, FILENAME_MAX - 1,
1429 "%s/.mmc", application_path);
1430 snprintf(temp_application_mmc_path, FILENAME_MAX - 1,
1431 "%s/.mmc", temp_application_path);
1433 ret = _app2sd_copy_ro_content(application_mmc_path,
1434 temp_application_mmc_path, dir_list);
1436 _E("copy ro content failed");
1440 ret = _app2sd_unmount_app_content(application_path);
1442 _E("unable to unmount the SD application");
1443 err_res = APP2EXT_ERROR_UNMOUNT;
1446 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1448 _E("unable to remove loopback setup");
1449 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1452 ret = _app2sd_unmount_app_content(temp_application_path);
1454 _E("unable to unmount the SD application");
1455 err_res = APP2EXT_ERROR_UNMOUNT;
1459 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1461 _E("unable to remove loopback setup");
1462 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1466 ret = _app2sd_delete_directory(loopback_device);
1468 _E("unable to delete (%s)", loopback_device);
1469 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1473 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1475 _E("unable to rename (%s)", temp_loopback_device);
1476 err_res = APP2EXT_ERROR_MOVE;
1480 ret = _app2sd_delete_directory(temp_application_path);
1482 _E("unable to delete (%s)", temp_application_path);
1483 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1487 return APP2EXT_SUCCESS;
1490 if (old_device_node) {
1491 free(old_device_node);
1492 old_device_node = NULL;
1495 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1497 _E("unable to remove loopback setup");
1498 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;