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.
29 #include "app2sd_internals.h"
31 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
32 #define DMCRYPT_ITER_TIME 50
33 #define DMCRYPT_KEY_LEN 128
36 static int _app2sd_make_directory(const char *path, uid_t uid)
40 mode_t mode = DIR_PERMS;
42 struct passwd *pwd_result;
45 ret = _app2sd_delete_directory(path);
47 _E("unable to delete (%s), errno(%d)", path, errno);
48 return APP2EXT_ERROR_DELETE_DIRECTORY;
51 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
52 if (ret != 0 || pwd_result == NULL) {
53 _E("get uid failed(%d)", ret);
54 return APP2EXT_ERROR_ACCESS_FILE;
56 _D("uid(%d), gid(%d)", uid, pwd.pw_gid);
58 /* create directory */
59 ret = mkdir(path, mode);
61 if (errno != EEXIST) {
62 _E("create directory failed, error is (%d)", errno);
63 return APP2EXT_ERROR_CREATE_DIRECTORY;
67 fd = open(path, O_RDONLY|O_DIRECTORY);
69 _E("can't open path(%s)", path);
70 return APP2EXT_ERROR_OPEN_DIR;
73 ret = fchmod(fd, 0755);
75 _E("change file permission error");
77 return APP2EXT_ERROR_ACCESS_FILE;
80 ret = fchown(fd, uid, pwd.pw_gid);
82 _E("change file owner error");
84 return APP2EXT_ERROR_ACCESS_FILE;
89 return APP2EXT_SUCCESS;
92 char *_app2sd_find_associated_device_node(const char *loopback_device)
97 char dev[FILENAME_MAX];
101 result = (char *)_app2sd_find_associated_device(loopback_device);
102 if (result == NULL) {
103 _D("there is no the associated file (%s)", loopback_device);
107 /* process the string*/
108 snprintf(dev, sizeof(dev), "%s", result);
110 if (strstr(dev, "dev") == NULL) {
111 _E("unable to find the associated file");
115 ret_result = strtok_r(dev, delims, &saveptr);
117 devnode = strdup(ret_result);
125 #define MAX_LOOP_COUNT 256
126 char *_app2sd_create_loopdevice_node(void)
128 mode_t mode = DIR_PERMS;
133 char dev_path[BUF_SIZE];
136 result = (char *)_app2sd_find_free_device();
137 _D("find_free_device(%s)", result);
139 if (result && strncmp(result, "/dev", strlen("/dev")) == 0) {
140 _D("device node candidate is (%s)", result);
144 _D("no device found, creating device node");
147 for (count = 0; count < MAX_LOOP_COUNT; count++) {
148 snprintf(dev_path, sizeof(dev_path), "/dev/loop%d", count);
149 _D("next dev path for checking is (%s)", dev_path);
150 fp = fopen(dev_path, "r+");
156 _D("device node candidate is (%s)", dev_path);
158 dev_node = makedev(DEV_MAJOR, count);
159 ret = mknod(dev_path, S_IFBLK | mode, dev_node);
161 _E("error while creating the device node: errno (%d)", errno);
165 result = strdup(dev_path);
167 _E("unable to allocate memory");
172 char *_app2sd_do_loopback_encryption_setup(const char *pkgid,
173 const char *loopback_device, uid_t uid)
181 _E("invalid argument");
185 /* get password for loopback encryption */
186 ret = _app2sd_initialize_db();
188 _E("app2sd db initialize failed");
192 passwd = _app2sd_get_password_from_db(pkgid, uid);
193 if (passwd == NULL) {
194 passwd = (char *)_app2sd_generate_password();
195 if (passwd == NULL) {
196 _E("unable to generate password");
200 ret = _app2sd_set_info_in_db(pkgid, passwd, loopback_device,
203 _E("unable to save info");
209 /* get free device node*/
210 device_node = _app2sd_create_loopdevice_node();
211 if (device_node == NULL) {
213 _E("unable to find free loopback node");
217 _D("device_node (%s)", device_node);
219 result = (char *)_app2sd_encrypt_device(device_node,
220 loopback_device, passwd);
222 if (result == NULL) {
223 _E("encryption failed");
227 _D("result (%s)", result);
233 char *_app2sd_do_loopback_duplicate_encryption_setup(const char *pkgid,
234 const char *temp_pkgid, const char *temp_loopback_device,
235 char *passwd, uid_t uid)
240 if (pkgid == NULL || temp_pkgid == NULL ||
241 temp_loopback_device == NULL || passwd == NULL) {
242 _E("invalid argument");
246 /* get free device node*/
247 device_node = _app2sd_create_loopdevice_node();
248 if (device_node == NULL) {
249 _E("unable to find free loopback node");
252 result = (char *)_app2sd_encrypt_device(device_node,
253 temp_loopback_device, passwd);
254 /* losetup does not forked or errmsg from losetup */
255 if (result == NULL || strlen(result)) {
256 _E("encryption failed");
257 if (result && strlen(result))
258 _E("error is (%s)", result);
269 int _app2sd_remove_loopback_encryption_setup(const char *loopback_device)
271 int ret = APP2EXT_SUCCESS;
275 dev_node = _app2sd_find_associated_device_node(loopback_device);
276 if (dev_node == NULL) {
277 _E("Unable to find the association");
278 ret = APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE;
281 result = (char *)_app2sd_detach_loop_device(dev_node);
282 if (result == NULL) {
283 _E("error in detaching");
284 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
296 int _app2sd_remove_all_loopback_encryption_setups(const char *loopback_device)
302 dev_node = _app2sd_find_associated_device_node(
304 if (dev_node == NULL) {
305 _E("finish to find the association");
306 ret = APP2EXT_SUCCESS;
310 _D("find node (%s)", dev_node);
312 result = (char *)_app2sd_detach_loop_device(dev_node);
314 if (result == NULL) {
315 _E("error in detaching");
316 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
325 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
326 int _app2sd_dmcrypt_setup_device(const char *pkgid,
327 const char *loopback_device, bool is_dup, uid_t uid)
331 char dmcrypt_setup_cmd[BUF_SIZE];
332 char err_buf[BUF_SIZE];
334 if (pkgid == NULL || loopback_device == NULL) {
335 _E("invalid argument");
336 return APP2EXT_ERROR_INVALID_ARGUMENTS;
339 /* get password for dmcrypt encryption */
340 ret = _app2sd_initialize_db();
342 _E("app2sd db initialize failed");
343 return APP2EXT_ERROR_DB_INITIALIZE;
346 passwd = _app2sd_get_password_from_db(pkgid, uid);
347 if (passwd == NULL) {
349 _E("no password found for (%s)", pkgid);
350 return APP2EXT_ERROR_SQLITE_REGISTRY;
352 passwd = _app2sd_generate_password();
353 if (passwd == NULL) {
354 _E("unable to generate password");
355 return APP2EXT_ERROR_PASSWD_GENERATION;
358 ret = _app2sd_set_info_in_db(pkgid, passwd, loopback_device,
361 _E("unable to save password");
363 return APP2EXT_ERROR_SQLITE_REGISTRY;
367 snprintf(dmcrypt_setup_cmd, sizeof(dmcrypt_setup_cmd),
368 "/bin/echo '%s' | /sbin/cryptsetup -q -i %d "
369 "-c aes-cbc-lmk -s %d --align-payload=8 luksFormat %s",
370 passwd, DMCRYPT_ITER_TIME, DMCRYPT_KEY_LEN,
373 ret = system(dmcrypt_setup_cmd);
375 strerror_r(errno, err_buf, sizeof(err_buf));
376 _E("Error setting up dmcrypt on app2sd file, error:%s, ret:%d",
378 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
384 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
385 bool is_dup, uid_t uid, char **dev_node)
389 char dmcrypt_open_cmd[BUF_SIZE];
390 char dev_name[BUF_SIZE];
393 if (pkgid == NULL || loopback_device == NULL) {
394 _E("invalid argument");
395 return APP2EXT_ERROR_INVALID_ARGUMENTS;
399 snprintf(dev_name, sizeof(dev_name), "%s.new_%d", pkgid, uid);
401 snprintf(dev_name, sizeof(dev_name), "%s_%d", pkgid, uid);
403 /* get password for dmcrypt encryption */
404 ret = _app2sd_initialize_db();
406 _E("app2sd db initialize failed");
407 return APP2EXT_ERROR_DB_INITIALIZE;
410 passwd = _app2sd_get_password_from_db(pkgid, uid);
411 if (passwd == NULL) {
412 _E("no password found for [%s]", pkgid);
413 return APP2EXT_ERROR_SQLITE_REGISTRY;
416 if (_app2sd_check_is_luks_device(loopback_device) == 0) {
417 _W("legacy image format!");
418 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
419 "/bin/echo '%s' | /sbin/cryptsetup "
420 "-M plain -c aes-cbc-plain -h plain open %s %s",
421 passwd, loopback_device, dev_name);
423 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
424 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen "
426 passwd, loopback_device, dev_name);
430 ret = system(dmcrypt_open_cmd);
432 strerror_r(errno, buf, sizeof(buf));
433 _E("error opening dmcrypt device, error: [%s]", buf);
434 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
437 snprintf(buf, sizeof(buf), "/dev/mapper/%s", dev_name);
438 *dev_node = strdup(buf);
439 if (*dev_node == NULL) {
440 _E("memory alloc failed");
441 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
447 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
450 char dev_node[BUF_SIZE];
451 char dmcrypt_close_cmd[BUF_SIZE];
452 char err_buf[BUF_SIZE];
456 _E("invalid argument");
457 return APP2EXT_ERROR_INVALID_ARGUMENTS;
460 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
462 _W("no associated device node(%s_%d) found", pkgid, uid);
463 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
468 snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
469 snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
470 "/sbin/cryptsetup -q luksClose %s", dev_node);
471 ret = system(dmcrypt_close_cmd);
473 strerror_r(errno, err_buf, sizeof(err_buf));
474 _E("error closing dmcrypt on app2sd file: %s", err_buf);
475 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
481 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
486 snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
487 if (access(buf, F_OK) == 0) {
488 dev_node = strdup(buf);
489 if (dev_node == NULL) {
490 _E("memory alloc failed");
493 _D("device_node: (%s)", dev_node);
496 _D("can not access dev_node(%s), errno(%d)", buf, errno);
501 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
502 const char *temp_loopback_device, uid_t uid)
507 if (pkgid == NULL || temp_loopback_device == NULL) {
508 _E("invalid argument");
512 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
515 _E("dmcrypt setup device error(%d)", ret);
519 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
522 _E("dmcrypt open device error");
530 int _app2sd_create_loopback_device(const char *pkgid,
531 const char *loopback_device, int size)
534 char command[FILENAME_MAX];
537 const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
538 "bs=1M", buff, NULL };
540 if (pkgid == NULL || size <= 0) {
541 _E("invalid argument");
542 return APP2EXT_ERROR_INVALID_ARGUMENTS;
545 fp = fopen(loopback_device, "r+");
547 _W("encrypted file already exists (%s)", loopback_device);
549 return APP2EXT_ERROR_PKG_EXISTS;
552 snprintf(command, sizeof(command), "of=%s", loopback_device);
553 snprintf(buff, sizeof(buff), "count=%d", size);
555 ret = _xsystem(argv);
557 _E("command (%s) failed, ret(%d), errno(%d)",
558 command, ret, errno);
563 int _app2sd_delete_loopback_device(const char *loopback_device)
567 ret = unlink(loopback_device);
569 if (errno == ENOENT) {
570 _W("unable to access file (%s)", loopback_device);
572 _E("unable to delete (%s)", loopback_device);
573 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
577 return APP2EXT_SUCCESS;
580 int _app2sd_create_file_system(const char *device_path)
585 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
587 if (device_path == NULL) {
589 return APP2EXT_ERROR_INVALID_ARGUMENTS;
592 /* Format the filesystem [create a filesystem]*/
593 fp = fopen(device_path, "r+");
595 strerror_r(errno, err_buf, sizeof(err_buf));
596 _E("unable to access (%s) error is (%d, %s)",
597 device_path, errno, err_buf);
598 return APP2EXT_ERROR_ACCESS_FILE;
602 ret = _xsystem(argv);
604 strerror_r(errno, err_buf, sizeof(err_buf));
605 _E("creating file system failed, error is (%s)", err_buf);
606 return APP2EXT_ERROR_CREATE_FS;
611 static int _app2sd_create_dir_with_link(const char *application_path,
612 const char *pkgid, const char *dir_name, uid_t uid)
615 char app_dir_mmc_path[FILENAME_MAX];
616 char app_dir_path[FILENAME_MAX];
618 snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
619 application_path, dir_name);
620 snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
621 application_path, dir_name);
623 ret = _app2sd_make_directory(app_dir_mmc_path, uid);
625 _E("create directory failed");
626 return APP2EXT_ERROR_CREATE_DIRECTORY;
629 ret = symlink(app_dir_mmc_path, app_dir_path);
631 if (errno == EEXIST) {
632 _D("file with symlink name present (%s)", app_dir_path);
634 _E("symbolic link creation failed, error: %d", errno);
635 return APP2EXT_ERROR_CREATE_SYMLINK;
639 return APP2EXT_SUCCESS;
642 static int _app2sd_create_directory_entry(const char *application_path,
643 const char *pkgid, GList *dir_list, uid_t uid)
647 app2ext_dir_details *dir_detail;
649 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
650 dir_detail = (app2ext_dir_details *)list->data;
651 if (dir_detail == NULL || dir_detail->name == NULL ||
652 dir_detail->type != APP2EXT_DIR_RO)
654 ret = _app2sd_create_dir_with_link(application_path,
655 pkgid, dir_detail->name, uid);
659 return APP2EXT_SUCCESS;
662 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
663 const char *dev, int mount_type, GList *dir_list,
664 app2sd_cmd cmd, uid_t uid)
668 char app_mmc_path[FILENAME_MAX];
669 char temp_path[FILENAME_MAX];
671 struct timespec time = {
673 .tv_nsec = 1000 * 1000 * 200
677 _E("input param is NULL (%s)", dev);
678 return APP2EXT_ERROR_INVALID_ARGUMENTS;
681 /* check directory existence */
682 fd = open(application_path, O_RDONLY | O_DIRECTORY);
684 _E("path(%s) error(%d)", application_path, errno);
685 return APP2EXT_ERROR_OPEN_DIR;
689 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
691 fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
693 _E("path(%s) error(%d)", app_mmc_path, errno);
694 return APP2EXT_ERROR_OPEN_DIR;
698 nanosleep(&time, NULL); /* 200ms sleep */
699 _D("give a delay for mount");
701 switch (mount_type) {
703 ret = mount(dev, app_mmc_path, FS_TYPE,
704 MS_MGC_VAL | MS_RDONLY | MS_NOSUID, NULL);
706 _E("read only mount failed, errono is (%d), "
707 "dev is (%s) path is (%s)",
708 errno, dev, app_mmc_path);
709 ret = APP2EXT_ERROR_MOUNT;
713 ret = mount(dev, app_mmc_path, FS_TYPE, MS_MGC_VAL | MS_NOSUID,
716 _E("read write mount failed, errono is (%d)", errno);
717 ret = APP2EXT_ERROR_MOUNT;
720 case MOUNT_TYPE_RW_NOEXEC:
721 ret = mount(dev, app_mmc_path, FS_TYPE,
722 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID, NULL);
724 _E("rwnx mount failed errono is (%d)", errno);
725 ret = APP2EXT_ERROR_MOUNT;
728 case MOUNT_TYPE_RD_REMOUNT:
729 ret = mount(dev, app_mmc_path, FS_TYPE,
730 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT | MS_NOSUID,
733 _E("read remount failed errono is (%d)", errno);
734 ret = APP2EXT_ERROR_MOUNT;
737 case MOUNT_TYPE_RW_REMOUNT:
738 ret = mount(dev, app_mmc_path, FS_TYPE,
739 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID, NULL);
740 strerror_r(errno, err_buf, sizeof(err_buf));
742 _E("read write remount failed errono(%d), errstr(%s)",
744 ret = APP2EXT_ERROR_MOUNT;
748 _E("invalid mount type");
752 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
753 cmd == APP2SD_PRE_UPGRADE) {
754 ret = _app2sd_create_directory_entry(application_path,
755 pkgid, dir_list, uid);
758 if (mount_type != MOUNT_TYPE_RD &&
759 mount_type != MOUNT_TYPE_RD_REMOUNT) {
760 /* change lost+found permission */
761 snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
763 ret = _app2sd_make_directory(temp_path, uid);
765 _E("create directory(%s) failed", temp_path);
766 return APP2EXT_ERROR_CREATE_DIRECTORY;
773 int _app2sd_unmount_app_content(const char *application_path)
776 char app_mmc_path[FILENAME_MAX];
779 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
781 ret = umount(app_mmc_path);
783 strerror_r(errno, err_buf, sizeof(err_buf));
784 _D("unable to umount the dir, ret(%d) error(%d, %s)",
785 ret, errno, err_buf);
791 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
796 ret = _app2sd_copy_dir(src_path, arch_path);
797 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
798 strerror_r(errno, err_buf, sizeof(err_buf));
799 _E("unable to copy from (%s) to (%s), err is (%s)",
800 src_path, arch_path, err_buf);
801 return APP2EXT_ERROR_MOVE;
804 ret = _app2sd_delete_directory(src_path);
806 _E("unable to delete (%s)", src_path);
807 return APP2EXT_ERROR_DELETE_DIRECTORY;
813 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
814 uid_t uid, char *mmc_path, char **image_path)
817 mode_t mode = DIR_PERMS;
818 char temp_dir_path[FILENAME_MAX];
819 char app_mmc_path[FILENAME_MAX];
820 char app_archive_path[FILENAME_MAX];
821 char application_path[FILENAME_MAX];
822 char loopback_device[FILENAME_MAX];
823 unsigned long long total_size = 0;
827 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
833 app2ext_dir_details *dir_detail;
836 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
837 loopback_device, sizeof(loopback_device));
841 _app2sd_set_application_path(pkgid, uid, application_path,
842 sizeof(application_path));
844 /* check whether application is in external memory or not */
845 fp = fopen(loopback_device, "r+");
847 _W("Already %s entry is present in the SD Card, "
848 "delete entry and go on without return", pkgid);
850 _app2sd_force_clean(pkgid, application_path, loopback_device,
854 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
856 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
859 ret = mkdir(app_mmc_path, mode);
861 if (errno != EEXIST) {
862 _E("unable to create directory for archiving,"
863 " error(%d)", errno);
864 return APP2EXT_ERROR_CREATE_DIRECTORY;
868 ret = mkdir(app_archive_path, mode);
870 if (errno != EEXIST) {
871 _E("unable to create directory for archiving,"
872 " error(%d)", errno);
873 return APP2EXT_ERROR_CREATE_DIRECTORY;
877 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
878 dir_detail = (app2ext_dir_details *)list->data;
879 if (dir_detail == NULL || dir_detail->name == NULL ||
880 dir_detail->type != APP2EXT_DIR_RO)
882 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
883 application_path, dir_detail->name);
884 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
885 total_size += _app2sd_calculate_dir_size(temp_dir_path);
888 reqd_size = ((total_size) / (1024 * 1024)) + 2;
889 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
891 /* find avialable free memory in the MMC card */
892 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
894 _E("unable to get available free memory in MMC (%d)", ret);
895 return APP2EXT_ERROR_MMC_STATUS;
897 /* if avaialalbe free memory in MMC is less than
898 * required size + 5MB, return error
900 if (reqd_disk_size > free_mmc_mem) {
901 _E("insufficient memory in MMC for "
902 "application installation (%d)", ret);
903 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
905 /* create a loopback device */
906 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
907 (reqd_disk_size + PKG_BUF_SIZE));
909 _E("loopback node creation failed");
913 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
914 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
916 _E("dmcrypt setup device error(%d)", ret);
917 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
920 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
923 _E("dmcrypt open device error");
924 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
927 /* perform loopback encryption setup */
928 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
929 loopback_device, uid);
931 _E("loopback encryption setup failed");
932 return APP2EXT_ERROR_DO_LOSETUP;
934 _D("device_node (%s)", device_node);
935 /* check whether loopback device is associated with
938 devi = _app2sd_find_associated_device_node(loopback_device);
940 _E("finding associated device node failed");
941 ret = APP2EXT_ERROR_DO_LOSETUP;
946 /* format the loopback file system */
947 ret = _app2sd_create_file_system(device_node);
949 _E("create ext4 filesystem failed");
950 ret = APP2EXT_ERROR_CREATE_FS;
954 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
955 dir_detail = (app2ext_dir_details *)list->data;
956 if (dir_detail == NULL || dir_detail->name == NULL ||
957 dir_detail->type != APP2EXT_DIR_RO)
959 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
960 application_path, dir_detail->name);
961 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
962 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
964 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
965 _E("unable to access (%s)", temp_dir_path);
967 _E("unable to copy from (%s) to (%s)",
975 /* mount the loopback encrypted pseudo device on
976 * application installation path as with Read Write permission
978 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
979 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
985 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
986 dir_detail = (app2ext_dir_details *)list->data;
987 if (dir_detail == NULL || dir_detail->name == NULL ||
988 dir_detail->type != APP2EXT_DIR_RO)
990 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
991 app_archive_path, dir_detail->name);
992 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
993 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
995 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
996 _E("unable to access (%s)", temp_dir_path);
998 strerror_r(errno, err_buf, sizeof(err_buf));
999 _E("unable to copy from (%s) to (%s),"
1000 " error is (%s)", temp_dir_path,
1001 app_mmc_path, err_buf);
1005 ret = _app2sd_delete_directory(temp_dir_path);
1007 _E("unable to delete (%s)", temp_dir_path);
1012 ret = _app2sd_delete_directory(app_archive_path);
1014 _E("unable to delete (%s)", app_archive_path);
1015 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
1019 *image_path = strdup(loopback_device);
1020 return APP2EXT_SUCCESS;
1030 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
1031 uid_t uid, char *mmc_path)
1034 mode_t mode = DIR_PERMS;
1035 char temp_dir_path[FILENAME_MAX];
1036 char app_mmc_path[FILENAME_MAX];
1037 char app_archive_path[FILENAME_MAX];
1038 char application_path[FILENAME_MAX];
1039 char loopback_device[FILENAME_MAX];
1043 app2ext_dir_details *dir_detail;
1045 int free_internal_mem;
1046 unsigned long long temp = 0;
1050 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
1051 loopback_device, sizeof(loopback_device));
1055 _app2sd_set_application_path(pkgid, uid, application_path,
1056 sizeof(application_path));
1058 /* check whether application is in external memory or not */
1059 fp = fopen(loopback_device, "r+");
1061 _E("application (%s) is not installed on SD Card",
1063 return APP2EXT_ERROR_FILE_ABSENT;
1067 /* find avialable free memory in the internal storage */
1068 ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
1069 &free_internal_mem);
1071 _E("unable to get available free memory in internal (%d)", ret);
1072 return APP2EXT_ERROR_MMC_STATUS;
1075 fp = fopen(loopback_device, "r+");
1077 _E("app entry is not present in SD card");
1078 return APP2EXT_ERROR_INVALID_PACKAGE;
1082 /* get installed app size*/
1083 temp = _app2sd_calculate_file_size(loopback_device);
1084 reqd_size = (int)((temp) / (1024 * 1024));
1085 _D("reqd size is (%d)", reqd_size);
1087 if (reqd_size == 0) {
1088 _E("app entry is not present in SD Card");
1089 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1092 _I("reqd size: (%d)MB, free internal mem: (%d)MB",
1093 reqd_size, free_internal_mem);
1095 /* if avaialalbe free memory in internal storage is
1096 * less than required size, return error
1098 if (reqd_size > free_internal_mem) {
1099 _E("innsufficient memory in internal storage"
1100 " for application installation (%d)", ret);
1101 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
1104 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1106 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1108 device_node = _app2sd_find_associated_device_node(loopback_device);
1110 if (device_node == NULL) {
1111 /* do loopback setup */
1112 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1113 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1114 false, uid, &device_node);
1116 _E("dmcrypt open device error(%d)", ret);
1117 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1120 device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1121 loopback_device, uid);
1122 if (device_node == NULL) {
1123 _E("loopback encryption setup failed");
1124 return APP2EXT_ERROR_DO_LOSETUP;
1127 mount_type = MOUNT_TYPE_RW;
1129 mount_type = MOUNT_TYPE_RW_REMOUNT;
1132 ret = _app2sd_mount_app_content(application_path,
1133 pkgid, device_node, mount_type,
1134 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1137 ret = APP2EXT_ERROR_MOUNT_PATH;
1141 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
1143 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
1146 ret = mkdir(app_archive_path, mode);
1148 if (errno != EEXIST) {
1149 _E("unable to create directory for archiving,"
1150 " error(%d)", errno);
1151 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
1156 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1157 dir_detail = (app2ext_dir_details *)list->data;
1158 if (dir_detail == NULL || dir_detail->name == NULL ||
1159 dir_detail->type != APP2EXT_DIR_RO)
1161 /* archiving code */
1162 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
1163 app_mmc_path, dir_detail->name);
1164 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
1165 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
1167 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1168 _E("unable to access (%s)", temp_dir_path);
1170 strerror_r(errno, err_buf, sizeof(err_buf));
1171 _E("unable to copy from (%s) to (%s),"
1172 "error is (%s)", temp_dir_path,
1173 app_archive_path, err_buf);
1177 /* delete the symbolic link files [bin, lib, res]*/
1178 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
1179 application_path, dir_detail->name);
1180 _D("unlink, temp_dir_path(%s)", temp_dir_path);
1181 ret = unlink(temp_dir_path);
1183 if (errno == ENOENT) {
1184 _W("(%s) does not exist", temp_dir_path);
1186 _E("unable to remove the symbolic link file "
1187 "(%s), it is already unlinked",
1192 /* Copy content to destination */
1193 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
1194 app_archive_path, dir_detail->name);
1195 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1196 ret = _app2sd_copy_dir(temp_dir_path, application_path);
1198 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1199 _E("unable to access (%s)", temp_dir_path);
1201 strerror_r(errno, err_buf, sizeof(err_buf));
1202 _E("unable to copy from (%s) to (%s), "
1203 "error is (%s)", temp_dir_path,
1204 application_path, err_buf);
1210 _D("copying file completed");
1211 ret = _app2sd_unmount_app_content(application_path);
1213 _E("unable to unmount SD directory for app (%s)", pkgid);
1215 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1216 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1218 _E("close dmcrypt device error(%d)", ret);
1220 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1222 _E("unable to detach loopback setup for (%s)", pkgid);
1225 ret = _app2sd_delete_loopback_device(loopback_device);
1227 _E("unable to delete the loopback device for (%s)", pkgid);
1229 ret = _app2sd_delete_directory(app_mmc_path);
1231 _E("unable to delete (%s)", app_mmc_path);
1233 ret = _app2sd_delete_directory(app_archive_path);
1235 _E("unable to delete (%s)", app_archive_path);
1237 /* remove passwrd from DB */
1238 ret = _app2sd_initialize_db();
1240 _E("app2sd db initialize failed");
1242 ret = _app2sd_remove_info_from_db(pkgid, uid);
1244 _E("cannot remove info from db");
1246 return APP2EXT_SUCCESS;
1255 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1256 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
1260 switch (move_type) {
1261 case APP2EXT_MOVE_TO_EXT:
1262 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1263 uid, mmc_path, image_path);
1265 _E("move app to external memory failed(%d)", ret);
1269 case APP2EXT_MOVE_TO_PHONE:
1270 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1273 _E("move app to internal memory failed(%d)", ret);
1278 _E("invalid argument");
1279 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1285 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1287 char path[FILENAME_MAX];
1290 app2ext_dir_details *dir_detail;
1292 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1293 dir_detail = (app2ext_dir_details *)list->data;
1294 if (dir_detail == NULL || dir_detail->name == NULL ||
1295 dir_detail->type != APP2EXT_DIR_RO)
1298 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1299 ret = _app2sd_copy_dir(path, dest);
1301 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1302 _E("unable to access (%s)", path);
1304 _E("unable to copy from (%s) "
1305 "to (%s), errno is (%d)",
1307 return APP2EXT_ERROR_MOVE;
1312 return APP2EXT_SUCCESS;
1315 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1316 const char *temp_pkgid, const char *temp_application_path,
1317 const char *temp_loopback_device, GList *dir_list,
1318 char *dev_node, int size, uid_t uid)
1322 #if !defined(TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION)
1328 /* create a new loopback device */
1329 ret = _app2sd_create_loopback_device(temp_pkgid,
1330 temp_loopback_device, (size + PKG_BUF_SIZE));
1332 _E("package already present");
1336 /* perform loopback encryption setup */
1337 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1338 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1339 temp_loopback_device, uid);
1341 _E("dmcrypt duplicate encryption setup failed");
1342 _app2sd_delete_loopback_device(temp_loopback_device);
1343 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1346 /* get password for loopback encryption */
1347 ret = _app2sd_initialize_db();
1349 _E("app2sd db initialize failed");
1350 return APP2EXT_ERROR_DB_INITIALIZE;
1353 passwd = _app2sd_get_password_from_db(pkgid, uid);
1354 if (passwd == NULL) {
1355 passwd = _app2sd_generate_password();
1356 if (passwd == NULL) {
1357 _E("unable to generate password");
1358 return APP2EXT_ERROR_PASSWD_GENERATION;
1360 ret = _app2sd_set_info_in_db(pkgid, passwd,
1361 loopback_device, uid);
1363 _E("unable to save info");
1365 return APP2EXT_ERROR_SQLITE_REGISTRY;
1370 dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid,
1371 temp_pkgid, temp_loopback_device, passwd, uid);
1373 _E("losetup failed, device node is (%s)", dev_node);
1374 _app2sd_delete_loopback_device(temp_loopback_device);
1376 return APP2EXT_ERROR_DO_LOSETUP;
1379 _D("duplicate setup SUCCESS");
1381 /* check whether loopback device is associated with
1382 * device node or not
1384 devi = _app2sd_find_associated_device_node(temp_loopback_device);
1386 _E("finding associated device node failed");
1387 err_res = APP2EXT_ERROR_DO_LOSETUP;
1391 _D("losetup SUCCESS");
1394 /* format the loopback file system */
1395 ret = _app2sd_create_file_system(dev_node);
1397 _E("creating fs failed");
1398 err_res = APP2EXT_ERROR_CREATE_FS;
1401 _D("create filesystem SUCCESS");
1403 /* do mounting for new dev*/
1404 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1405 dev_node, MOUNT_TYPE_RW, dir_list,
1406 APP2SD_PRE_UPGRADE, uid);
1408 _E("remount failed");
1409 err_res = APP2EXT_ERROR_MOUNT_PATH;
1413 return APP2EXT_SUCCESS;
1417 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1418 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1420 _E("close dmcrypt device error(%d)", ret);
1422 result = _app2sd_detach_loop_device(dev_node);
1426 _app2sd_delete_loopback_device(temp_loopback_device);
1433 int _app2sd_update_loopback_device_size(const char *pkgid,
1434 const char *loopback_device, const char *application_path,
1435 const char *temp_pkgid, const char *temp_loopback_device,
1436 const char *temp_application_path, int size, GList *dir_list,
1440 char *old_device_node;
1442 char app_mmc_path[FILENAME_MAX];
1443 char temp_app_mmc_path[FILENAME_MAX];
1446 ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1447 temp_application_path, temp_loopback_device,
1448 dir_list, NULL, size, uid);
1450 _E("creating duplicate device failed");
1454 /* get the associated device node for SD card applicatione */
1455 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1457 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1459 old_device_node = _app2sd_find_associated_device_node(loopback_device);
1461 if (old_device_node == NULL) {
1462 /* do loopback setup */
1463 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1464 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1465 false, uid, &old_device_node);
1467 _E("dmcrypt open device error");
1468 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1472 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid,
1473 loopback_device, uid);
1474 if (old_device_node == NULL) {
1475 _E("loopback encryption setup failed");
1476 err_res = APP2EXT_ERROR_DO_LOSETUP;
1480 mount_type = MOUNT_TYPE_RW;
1482 mount_type = MOUNT_TYPE_RW_REMOUNT;
1486 ret = _app2sd_mount_app_content(application_path, pkgid,
1487 old_device_node, mount_type, dir_list,
1488 APP2SD_PRE_UPGRADE, uid);
1490 _E("remount failed");
1491 err_res = APP2EXT_ERROR_MOUNT_PATH;
1494 snprintf(app_mmc_path, sizeof(app_mmc_path),
1495 "%s/.mmc", application_path);
1496 snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1497 "%s/.mmc", temp_application_path);
1499 ret = _app2sd_copy_ro_content(app_mmc_path,
1500 temp_app_mmc_path, dir_list);
1502 _E("copy ro content failed");
1506 ret = _app2sd_unmount_app_content(application_path);
1508 _E("unable to unmount the SD application");
1509 err_res = APP2EXT_ERROR_UNMOUNT;
1512 ret = _app2sd_unmount_app_content(temp_application_path);
1514 _E("unable to unmount the SD application");
1515 err_res = APP2EXT_ERROR_UNMOUNT;
1519 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1520 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1522 _E("close dmcrypt device error(%d)", ret);
1523 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1527 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1529 _E("close dmcrypt device error(%d)", ret);
1530 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1534 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1536 _E("unable to remove loopback setup");
1537 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1540 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1542 _E("unable to remove loopback setup");
1543 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1548 ret = _app2sd_delete_directory(loopback_device);
1550 _E("unable to delete (%s)", loopback_device);
1551 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1555 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1557 _E("unable to rename (%s)", temp_loopback_device);
1558 err_res = APP2EXT_ERROR_MOVE;
1562 ret = _app2sd_delete_directory(temp_application_path);
1564 _E("unable to delete (%s)", temp_application_path);
1565 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1569 return APP2EXT_SUCCESS;
1572 if (old_device_node)
1573 free(old_device_node);
1575 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1576 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1578 _E("close dmcrypt device error(%d)", ret);
1580 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1582 _E("close dmcrypt device error(%d)", ret);
1584 ret = _app2sd_remove_loopback_encryption_setup(loopback_device);
1586 _E("unable to remove loopback setup");
1588 ret = _app2sd_remove_loopback_encryption_setup(temp_loopback_device);
1590 _E("unable to remove loopback setup");
1593 _app2sd_delete_loopback_device(temp_loopback_device);
1595 ret = _app2sd_delete_directory(temp_application_path);
1597 _E("unable to delete (%s)", temp_application_path);
1602 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1603 const char *loopback_device, uid_t uid)
1607 /* unmount the loopback encrypted pseudo device from
1608 * the application installation path
1610 ret = _app2sd_unmount_app_content(application_path);
1612 _W("unable to unmount the app content (%d)", ret);
1614 /* detach the loopback encryption setup for the application */
1615 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
1616 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1618 _W("close dmcrypt device error (%d)", ret);
1620 ret = _app2sd_remove_all_loopback_encryption_setups(loopback_device);
1622 _W("unable to detach the loopback encryption setup for "
1626 /* delete the loopback device from the SD card */
1627 ret = _app2sd_delete_loopback_device(loopback_device);
1629 _W("unable to detach the loopback encryption setup for "
1632 /* delete symlink */
1633 _app2sd_delete_symlink(application_path);
1635 /* remove passwrd from DB */
1636 ret = _app2sd_initialize_db();
1638 _W("app2sd db initialize failed");
1640 ret = _app2sd_remove_info_from_db(pkgid, uid);
1642 _W("cannot remove info from db");