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,};
750 /* check whether MMC is present or not */
751 ret = _app2sd_check_mmc_status();
753 _E("MMC not preset OR Not ready(%d)", ret);
754 return APP2EXT_ERROR_MMC_STATUS;
757 if (_is_global(uid)) {
758 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
759 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
760 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
763 tzplatform_set_user(uid);
764 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
765 tzplatform_getenv(TZ_USER_APP), pkgid);
766 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
767 APP2SD_PATH, tzplatform_getenv(TZ_USER_NAME), pkgid);
768 tzplatform_reset_user();
770 _D("application_path = (%s)", application_path);
771 _D("loopback_device = (%s)", loopback_device);
773 /* check whether application is in external memory or not */
774 fp = fopen(loopback_device, "r+");
776 _W("Already %s entry is present in the SD Card, " \
777 "delete entry and go on without return", pkgid);
779 app2sd_usr_force_clean(pkgid, uid);
782 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
784 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
786 _D("application_mmc_path = (%s)", application_mmc_path);
787 _D("application_archive_path = (%s)", application_archive_path);
789 ret = mkdir(application_archive_path, mode);
791 if (errno != EEXIST) {
792 _E("unable to create directory for archiving," \
793 " error(%d)", errno);
794 return APP2EXT_ERROR_CREATE_DIRECTORY;
798 list = g_list_first(dir_list);
800 dir_detail = (app2ext_dir_details *)list->data;
801 if (dir_detail && dir_detail->name
802 && dir_detail->type == APP2EXT_DIR_RO) {
803 memset(temp_dir_path, '\0', FILENAME_MAX);
804 snprintf(temp_dir_path, FILENAME_MAX,
805 "%s/%s", application_path,
807 _D("cal size of app dirs, temp_dir_path(%s)",
810 _app2sd_calculate_dir_size(temp_dir_path);
812 list = g_list_next(list);
815 reqd_size = ((total_size) / ( 1024 * 1024)) + 2;
816 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
818 /* find avialable free memory in the MMC card */
819 ret = _app2sd_get_available_free_memory(MMC_PATH, &free_mmc_mem);
821 _E("unable to get available free memory in MMC (%d)", ret);
822 return APP2EXT_ERROR_MMC_STATUS;
824 /* if avaialalbe free memory in MMC is less than
825 * required size + 5MB, return error
827 if (reqd_disk_size > free_mmc_mem) {
828 _E("insufficient memory in MMC for application installation (%d)",
830 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
832 /* create a loopback device */
833 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
834 (reqd_disk_size + PKG_BUF_SIZE));
836 _E("loopback node creation failed");
839 /* perform loopback encryption setup */
840 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
841 loopback_device, uid);
843 _E("loopback encryption setup failed");
844 return APP2EXT_ERROR_DO_LOSETUP;
846 _D("device_node (%s)", device_node);
847 /* check whether loopback device is associated with device node or not */
848 devi = _app2sd_find_associated_device_node(loopback_device);
850 _E("finding associated device node failed");
851 return APP2EXT_ERROR_DO_LOSETUP;
856 /* format the loopback file system */
857 ret = _app2sd_create_file_system(device_node);
859 _E("create ext4 filesystem failed");
860 return APP2EXT_ERROR_CREATE_FS;
863 list = g_list_first(dir_list);
865 dir_detail = (app2ext_dir_details *)list->data;
866 if (dir_detail && dir_detail->name
867 && dir_detail->type == APP2EXT_DIR_RO) {
868 memset(temp_dir_path, '\0', FILENAME_MAX);
869 snprintf(temp_dir_path, FILENAME_MAX,
870 "%s/%s", application_path,
872 _D("app2archive, temp_dir_path(%s)",
874 ret = _app2sd_move_to_archive(temp_dir_path,
875 application_archive_path);
877 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
878 _E("unable to access (%s)",
881 _E("unable to copy from (%s) to (%s)",
883 application_archive_path);
888 list = g_list_next(list);
891 /* mount the loopback encrypted pseudo device on application installation path
892 * as with Read Write permission
894 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
895 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
901 list = g_list_first(dir_list);
903 dir_detail = (app2ext_dir_details *)list->data;
904 if (dir_detail && dir_detail->name
905 && dir_detail->type == APP2EXT_DIR_RO) {
906 memset(temp_dir_path, '\0', FILENAME_MAX);
907 snprintf(temp_dir_path, FILENAME_MAX,
908 "%s/%s", application_archive_path,
910 _D("archive2mmc, temp_dir_path(%s)",
912 ret = _app2sd_copy_dir(temp_dir_path,
913 application_mmc_path);
915 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
916 _E("unable to access (%s)",
920 err_buf, sizeof(err_buf));
921 _E("unable to copy from (%s) to (%s)," \
924 application_mmc_path, err_buf);
928 ret = _app2sd_delete_directory(temp_dir_path);
930 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
931 _E("unable to access (%s)",
934 _E("unable to delete (%s)",
940 list = g_list_next(list);
943 ret = _app2sd_delete_directory(application_archive_path);
945 _E("unable to delete (%s)", application_archive_path);
946 return APP2EXT_ERROR_DELETE_DIRECTORY;
949 ret = _app2sd_apply_app_smack(application_path, pkgid, dir_list, uid);
951 _E("unable to apply app smack");
952 return APP2EXT_ERROR_MOVE;
955 /* re-mount the loopback encrypted pseudo device on application installation path
956 * as with Read Only permission
958 ret = _app2sd_unmount_app_content(application_path);
960 _E("unmount error (%d)", ret);
961 return APP2EXT_ERROR_UNMOUNT;
963 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
965 _E("unable to detach loopback setup for (%s)",
967 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
970 return APP2EXT_SUCCESS;
973 int _app2sd_move_app_to_internal(const char *pkgid, GList* dir_list, uid_t uid)
975 int ret = APP2EXT_SUCCESS;
976 mode_t mode = DIR_PERMS;
977 char temp_dir_path[FILENAME_MAX] = { 0, };
978 char application_mmc_path[FILENAME_MAX] = { 0, };
979 char application_archive_path[FILENAME_MAX] = { 0, };
980 char application_path[FILENAME_MAX] = { 0, };
981 char loopback_device[FILENAME_MAX] = { 0, };
982 char *device_node = NULL;
985 app2ext_dir_details* dir_detail = NULL;
987 int free_internal_mem = 0;
988 struct statvfs buf = {0,};
989 unsigned long long temp = 0;
990 char err_buf[1024] = {0,};
992 /* check whether MMC is present or not */
993 ret = _app2sd_check_mmc_status();
995 _E("MMC not preset OR Not ready(%d)", ret);
996 return APP2EXT_ERROR_MMC_STATUS;
999 if (_is_global(uid)) {
1000 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1001 tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
1002 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s",
1003 APP2SD_PATH, pkgid);
1005 tzplatform_set_user(uid);
1006 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
1007 tzplatform_getenv(TZ_USER_APP), pkgid);
1008 snprintf(loopback_device, FILENAME_MAX - 1, "%s/%s/%s",
1009 APP2SD_PATH, tzplatform_getenv(TZ_USER_NAME), pkgid);
1010 tzplatform_reset_user();
1012 _D("application_path = (%s)", application_path);
1013 _D("loopback_device = (%s)", loopback_device);
1015 /* check whether application is in external memory or not */
1016 fp = fopen(loopback_device, "r+");
1018 _E("application (%s) is not installed on SD Card",
1020 return APP2EXT_ERROR_FILE_ABSENT;
1026 memset((void *)&buf, '\0', sizeof(struct statvfs));
1027 ret = statvfs(INTERNAL_STORAGE_PATH, &buf);
1029 temp = (buf.f_bsize * buf.f_bavail) / (1024 * 1024);
1030 free_internal_mem = (int)temp;
1032 _E("unable to get internal storage size");
1033 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1036 fp = fopen(loopback_device, "r+");
1038 _E("app entry is not present in SD card");
1039 return APP2EXT_ERROR_INVALID_PACKAGE;
1043 /* get installed app size*/
1044 temp = _app2sd_calculate_file_size(loopback_device);
1045 reqd_size = (int)((temp) / (1024 * 1024));
1046 _D("reqd size is (%d)", reqd_size);
1048 if (reqd_size == 0) {
1049 _E("app entry is not present in SD Card");
1050 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1053 _D("reqd size: (%d)MB, free internal mem: (%d)MB",
1054 reqd_size, free_internal_mem);
1056 /* if avaialalbe free memory in internal storage is
1057 * less than required size, return error
1059 if (reqd_size > free_internal_mem) {
1060 _E("innsufficient memory in internal storage" \
1061 " for application installation (%d)", ret);
1062 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1065 device_node = _app2sd_find_associated_device_node(loopback_device);
1066 if (NULL == device_node) {
1067 /* do loopback setup */
1068 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1069 loopback_device, uid);
1070 if (device_node == NULL) {
1071 _E("loopback encryption setup failed");
1072 return APP2EXT_ERROR_DO_LOSETUP;
1075 ret = _app2sd_mount_app_content(application_path,
1076 pkgid, device_node, MOUNT_TYPE_RW,
1077 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1080 return APP2EXT_ERROR_MOUNT_PATH;
1083 /* do re-mounting */
1084 ret = _app2sd_mount_app_content(application_path,
1085 pkgid, device_node, MOUNT_TYPE_RW_REMOUNT,
1086 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1088 _E("re-mount failed");
1089 return APP2EXT_ERROR_MOUNT_PATH;
1093 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
1095 snprintf(application_archive_path, FILENAME_MAX - 1, "%s/.archive",
1097 _D("application_mmc_path = (%s)", application_mmc_path);
1098 _D("application_archive_path = (%s)", application_archive_path);
1100 ret = mkdir(application_archive_path, mode);
1102 if (errno != EEXIST) {
1103 _E("unable to create directory for archiving," \
1104 " error(%d)", errno);
1105 return APP2EXT_ERROR_CREATE_DIRECTORY;
1109 list = g_list_first(dir_list);
1111 dir_detail = (app2ext_dir_details *)list->data;
1112 if (dir_detail && dir_detail->name
1113 && dir_detail->type == APP2EXT_DIR_RO) {
1114 /* archiving code */
1115 memset(temp_dir_path, '\0', FILENAME_MAX);
1116 snprintf(temp_dir_path, FILENAME_MAX,
1117 "%s/%s", application_mmc_path,
1119 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1120 ret = _app2sd_copy_dir(temp_dir_path,
1121 application_archive_path);
1123 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1124 _E("unable to access (%s)",
1128 err_buf, sizeof(err_buf));
1129 _E("unable to copy from (%s) to (%s),"
1132 application_archive_path, err_buf);
1137 /* delete the symbolic link files [bin, lib, res]*/
1138 memset(temp_dir_path, '\0', FILENAME_MAX);
1139 snprintf(temp_dir_path, FILENAME_MAX,
1140 "%s/%s", application_path,
1142 _D("unlink, temp_dir_path(%s)", temp_dir_path);
1143 ret = unlink(temp_dir_path);
1145 if (errno == ENOENT) {
1146 _E("directory (%s) does not exist",
1149 _E("unable to remove the symbolic link file (%s)," \
1150 " it is already unlinked",
1156 /* Copy content to destination */
1157 memset(temp_dir_path, '\0', FILENAME_MAX);
1158 snprintf(temp_dir_path, FILENAME_MAX,
1159 "%s/%s", application_archive_path,
1161 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1162 ret = _app2sd_copy_dir(temp_dir_path, application_path);
1164 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1165 _E("unable to access (%s)",
1169 err_buf, sizeof(err_buf));
1170 _E("unable to copy from (%s) to (%s) " \
1173 application_path, err_buf);
1178 list = g_list_next(list);
1181 _D("copying file completed");
1182 ret = _app2sd_unmount_app_content(application_path);
1184 _E("unable to unmount SD directory for app (%s)",
1186 return APP2EXT_ERROR_UNMOUNT;
1188 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1190 _E("unable to detach loopback setup for (%s)",
1192 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
1194 ret = _app2sd_delete_loopback_device(loopback_device);
1196 _E("unable to delete the loopback device for (%s)",
1198 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1200 ret = _app2sd_delete_directory(application_mmc_path);
1202 _E("unable to delete (%s)", application_mmc_path);
1203 return APP2EXT_ERROR_DELETE_DIRECTORY;
1205 ret = _app2sd_delete_directory(application_archive_path);
1207 _E("unable to delete (%s)", application_archive_path);
1208 return APP2EXT_ERROR_DELETE_DIRECTORY;
1211 return APP2EXT_SUCCESS;
1214 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1215 GList* dir_list, uid_t uid)
1217 int ret = APP2EXT_SUCCESS;
1219 /* Check whether MMC is present or not */
1220 ret = _app2sd_check_mmc_status();
1222 _E("MMC not preset OR Not ready(%d)", ret);
1223 return APP2EXT_ERROR_MMC_STATUS;
1226 switch (move_type) {
1227 case APP2EXT_MOVE_TO_EXT:
1228 ret = _app2sd_move_app_to_external(pkgid, dir_list, uid);
1230 _E("move app to external memory failed(%d)", ret);
1234 case APP2EXT_MOVE_TO_PHONE:
1235 ret = _app2sd_move_app_to_internal(pkgid, dir_list, uid);
1237 _E("move app to internal memory failed(%d)", ret);
1242 _E("invalid argument");
1243 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1249 int _app2sd_copy_ro_content(const char *src, const char *dest, GList* dir_list)
1251 char path[FILENAME_MAX] = { 0, };
1252 int ret = APP2EXT_SUCCESS;
1254 app2ext_dir_details* dir_detail = NULL;
1256 list = g_list_first(dir_list);
1258 dir_detail = (app2ext_dir_details *)list->data;
1259 if (dir_detail && dir_detail->name
1260 && dir_detail->type == APP2EXT_DIR_RO) {
1261 memset((void *)&path, '\0', FILENAME_MAX);
1262 snprintf(path, FILENAME_MAX - 1, "%s/%s", src,
1264 ret = _app2sd_copy_dir(path, dest);
1266 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1267 _E("unable to access (%s)", path);
1269 _E("unable to copy from (%s) " \
1270 "to (%s), errno is (%d)",
1272 return APP2EXT_ERROR_MOVE;
1276 list = g_list_next(list);
1279 return APP2EXT_SUCCESS;
1282 int _app2sd_duplicate_device(const char *pkgid,
1283 const char *loopback_device,
1284 const char *temp_pkgid,
1285 const char *temp_application_path,
1286 const char *temp_loopback_device,
1287 GList* dir_list, char *dev_node, int size,
1293 char *result = NULL;
1295 /* create a new loopback device */
1296 ret = _app2sd_create_loopback_device(temp_pkgid,
1297 temp_loopback_device, (size + PKG_BUF_SIZE));
1299 _E("package already present");
1303 /* perform loopback encryption setup */
1304 dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1305 temp_pkgid, temp_loopback_device, uid);
1307 _E("losetup failed, device node is (%s)", dev_node);
1308 _app2sd_delete_loopback_device(loopback_device);
1309 _E("create ext filesystem failed");
1310 return APP2EXT_ERROR_DO_LOSETUP;
1312 _D("duplicate setup SUCCESS");
1314 /* check whether loopback device is associated with
1315 * device node or not
1317 devi = _app2sd_find_associated_device_node(temp_loopback_device);
1319 _E("finding associated device node failed");
1320 err_res = APP2EXT_ERROR_DO_LOSETUP;
1323 _D("losetup SUCCESS");
1325 /* format the loopback file system */
1326 ret = _app2sd_create_file_system(dev_node);
1328 _E("creating fs failed");
1329 err_res = APP2EXT_ERROR_CREATE_FS;
1332 _D("create filesystem SUCCESS");
1334 /* do mounting for new dev*/
1335 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1336 dev_node, MOUNT_TYPE_RW, dir_list,
1337 APP2SD_PRE_UPGRADE, uid);
1339 _E("remount failed");
1340 err_res = APP2EXT_ERROR_MOUNT_PATH;
1349 return APP2EXT_SUCCESS;
1353 result = _app2sd_detach_loop_device(dev_node);
1358 _app2sd_delete_loopback_device(loopback_device);
1370 int _app2sd_update_loopback_device_size(const char *pkgid,
1371 const char *loopback_device,
1372 const char *application_path,
1373 const char *temp_pkgid,
1374 const char *temp_loopback_device,
1375 const char *temp_application_path,
1376 int size, GList* dir_list,
1380 char *device_node = NULL;
1381 char *old_device_node = NULL;
1383 char application_mmc_path[FILENAME_MAX] = { 0, };
1384 char temp_application_mmc_path[FILENAME_MAX] = { 0, };
1386 ret = _app2sd_duplicate_device(pkgid, loopback_device,
1387 temp_pkgid, temp_application_path, temp_loopback_device,
1388 dir_list, device_node, size, uid);
1390 _E("creating duplicate device failed");
1394 /* get the associated device node for SD card applicatione */
1395 old_device_node = _app2sd_find_associated_device_node(loopback_device);
1396 if (NULL == old_device_node) {
1397 /* do loopback setup */
1398 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1399 loopback_device, uid);
1400 if (old_device_node == NULL) {
1401 _E("loopback encryption setup failed");
1402 err_res = APP2EXT_ERROR_DO_LOSETUP;
1406 ret = _app2sd_mount_app_content(application_path, pkgid,
1407 old_device_node, MOUNT_TYPE_RW, dir_list,
1408 APP2SD_PRE_UPGRADE, uid);
1410 _E("remount failed");
1411 err_res = APP2EXT_ERROR_MOUNT_PATH;
1414 /* do re-mounting */
1415 ret = _app2sd_mount_app_content(application_path, pkgid,
1416 old_device_node, MOUNT_TYPE_RW_REMOUNT, dir_list,
1417 APP2SD_PRE_UPGRADE, uid);
1419 _E("remount failed");
1420 err_res = APP2EXT_ERROR_MOUNT_PATH;
1424 snprintf(application_mmc_path, FILENAME_MAX - 1,
1425 "%s/.mmc", application_path);
1426 snprintf(temp_application_mmc_path, FILENAME_MAX - 1,
1427 "%s/.mmc", temp_application_path);
1429 ret = _app2sd_copy_ro_content(application_mmc_path,
1430 temp_application_mmc_path, dir_list);
1432 _E("copy ro content failed");
1436 ret = _app2sd_unmount_app_content(application_path);
1438 _E("unable to unmount the SD application");
1439 err_res = APP2EXT_ERROR_UNMOUNT;
1442 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1444 _E("unable to remove loopback setup");
1445 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1448 ret = _app2sd_unmount_app_content(temp_application_path);
1450 _E("unable to unmount the SD application");
1451 err_res = APP2EXT_ERROR_UNMOUNT;
1455 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1457 _E("unable to remove loopback setup");
1458 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1462 ret = _app2sd_delete_directory(loopback_device);
1464 _E("unable to delete (%s)", loopback_device);
1465 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1469 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1471 _E("unable to rename (%s)", temp_loopback_device);
1472 err_res = APP2EXT_ERROR_MOVE;
1476 ret = _app2sd_delete_directory(temp_application_path);
1478 _E("unable to delete (%s)", temp_application_path);
1479 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1483 return APP2EXT_SUCCESS;
1486 if (old_device_node) {
1487 free(old_device_node);
1488 old_device_node = NULL;
1491 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1493 _E("unable to remove loopback setup");
1494 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;