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 #define DMCRYPT_ITER_TIME 50
32 #define DMCRYPT_KEY_LEN 128
34 static int _app2sd_make_directory(const char *path, uid_t uid)
38 mode_t mode = DIR_PERMS;
40 struct passwd *pwd_result;
43 ret = _app2sd_delete_directory(path);
45 _E("unable to delete (%s), errno(%d)", path, errno);
46 return APP2EXT_ERROR_DELETE_DIRECTORY;
49 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
50 if (ret != 0 || pwd_result == NULL) {
51 _E("get uid failed(%d)", ret);
52 return APP2EXT_ERROR_ACCESS_FILE;
54 _D("uid(%d), gid(%d)", uid, pwd.pw_gid);
56 /* create directory */
57 ret = mkdir(path, mode);
59 if (errno != EEXIST) {
60 _E("create directory failed, error is (%d)", errno);
61 return APP2EXT_ERROR_CREATE_DIRECTORY;
65 fd = open(path, O_RDONLY|O_DIRECTORY);
67 _E("can't open path(%s)", path);
68 return APP2EXT_ERROR_OPEN_DIR;
71 ret = fchmod(fd, 0755);
73 _E("change file permission error");
75 return APP2EXT_ERROR_ACCESS_FILE;
78 ret = fchown(fd, uid, pwd.pw_gid);
80 _E("change file owner error");
82 return APP2EXT_ERROR_ACCESS_FILE;
87 return APP2EXT_SUCCESS;
90 int _app2sd_dmcrypt_setup_device(const char *pkgid,
91 const char *loopback_device, bool is_dup, uid_t uid)
95 char dmcrypt_setup_cmd[BUF_SIZE];
96 char err_buf[BUF_SIZE];
99 if (pkgid == NULL || loopback_device == NULL) {
100 _E("invalid argument");
101 return APP2EXT_ERROR_INVALID_ARGUMENTS;
104 /* get password for dmcrypt encryption */
105 ret = _app2sd_initialize_db();
107 _E("app2sd db initialize failed");
108 return APP2EXT_ERROR_DB_INITIALIZE;
111 passwd = _app2sd_get_password_from_db(pkgid, uid);
112 if (passwd == NULL) {
114 _E("no password found for (%s)", pkgid);
115 return APP2EXT_ERROR_SQLITE_REGISTRY;
117 passwd = _app2sd_generate_password();
118 if (passwd == NULL) {
119 _E("unable to generate password");
120 return APP2EXT_ERROR_PASSWD_GENERATION;
123 ret = _app2sd_set_info_in_db(pkgid, passwd, loopback_device,
126 _E("unable to save password");
128 return APP2EXT_ERROR_SQLITE_REGISTRY;
132 snprintf(dmcrypt_setup_cmd, sizeof(dmcrypt_setup_cmd),
133 "/bin/echo '%s' | /sbin/cryptsetup -q -i %d "
134 "-c aes-cbc-lmk -s %d --align-payload=8 luksFormat %s",
135 passwd, DMCRYPT_ITER_TIME, DMCRYPT_KEY_LEN,
137 memset(passwd, 0, strlen(passwd));
139 ret = system(dmcrypt_setup_cmd);
140 memset(dmcrypt_setup_cmd, 0, BUF_SIZE);
142 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
143 _E("Error setting up dmcrypt on app2sd file, error:%s, ret:%d",
145 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
151 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
152 bool is_dup, uid_t uid, char **dev_node)
157 char dmcrypt_open_cmd[BUF_SIZE];
158 char dev_name[BUF_SIZE];
162 if (pkgid == NULL || loopback_device == NULL) {
163 _E("invalid argument");
164 return APP2EXT_ERROR_INVALID_ARGUMENTS;
168 snprintf(dev_name, sizeof(dev_name), "%s.new_%d", pkgid, uid);
170 snprintf(dev_name, sizeof(dev_name), "%s_%d", pkgid, uid);
172 /* get password for dmcrypt encryption */
173 ret = _app2sd_initialize_db();
175 _E("app2sd db initialize failed");
176 return APP2EXT_ERROR_DB_INITIALIZE;
179 passwd = _app2sd_get_password_from_db(pkgid, uid);
180 if (passwd == NULL) {
181 _E("no password found for [%s]", pkgid);
182 return APP2EXT_ERROR_SQLITE_REGISTRY;
185 if (_app2sd_check_is_luks_device(loopback_device) == 0) {
186 _W("legacy image format!");
187 ret = snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
188 "/bin/echo '%s' | /sbin/cryptsetup "
189 "-M plain -c aes-cbc-plain -h plain open %s %s",
190 passwd, loopback_device, dev_name);
191 if (ret < 0 || ret > sizeof(dmcrypt_open_cmd)) {
193 _E("snprintf fail\n");
197 ret = snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
198 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen "
200 passwd, loopback_device, dev_name);
201 if (ret < 0 || ret > sizeof(dmcrypt_open_cmd)) {
202 _E("snprintf fail\n");
209 ret = system(dmcrypt_open_cmd);
211 err_str = strerror_r(errno, buf, sizeof(buf));
212 _E("error opening dmcrypt device, error: [%s]", err_str);
213 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
216 size = strlen("/dev/mapper/%s") + strlen(dev_name) + 1;
217 *dev_node = (char *)malloc(size);
218 if (*dev_node == NULL) {
219 _E("memory alloc failed");
220 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
222 ret = snprintf(*dev_node, size, "/dev/mapper/%s", dev_name);
223 if (ret < 0 || ret > size) {
224 _E("snprintf fail\n");
232 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
235 char dev_node[BUF_SIZE];
236 char dmcrypt_close_cmd[BUF_SIZE];
237 char err_buf[BUF_SIZE];
242 _E("invalid argument");
243 return APP2EXT_ERROR_INVALID_ARGUMENTS;
246 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
248 _W("no associated device node(%s_%d) found", pkgid, uid);
249 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
254 ret = snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
255 if (ret < 0 || ret > sizeof(dev_node)) {
257 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
259 ret = snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
260 "/sbin/cryptsetup -q luksClose %s", dev_node);
261 if (ret < 0 || ret > sizeof(dmcrypt_close_cmd)) {
263 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
265 ret = system(dmcrypt_close_cmd);
267 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
268 _E("error closing dmcrypt on app2sd file: %s", err_str);
269 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
275 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
280 snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
281 if (access(buf, F_OK) == 0) {
282 dev_node = strdup(buf);
283 if (dev_node == NULL) {
284 _E("memory alloc failed");
287 _D("device_node: (%s)", dev_node);
290 _D("can not access dev_node(%s), errno(%d)", buf, errno);
295 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
296 const char *temp_loopback_device, uid_t uid)
301 if (pkgid == NULL || temp_loopback_device == NULL) {
302 _E("invalid argument");
306 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
309 _E("dmcrypt setup device error(%d)", ret);
313 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
316 _E("dmcrypt open device error");
323 int _app2sd_create_loopback_device(const char *pkgid,
324 const char *loopback_device, int size)
327 char command[FILENAME_MAX];
330 const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
331 "bs=1M", buff, NULL };
333 if (pkgid == NULL || size <= 0) {
334 _E("invalid argument");
335 return APP2EXT_ERROR_INVALID_ARGUMENTS;
338 fp = fopen(loopback_device, "r+");
340 _W("encrypted file already exists (%s)", loopback_device);
342 return APP2EXT_ERROR_PKG_EXISTS;
345 snprintf(command, sizeof(command), "of=%s", loopback_device);
346 snprintf(buff, sizeof(buff), "count=%d", size);
348 ret = _xsystem(argv);
350 _E("command (%s) failed, ret(%d), errno(%d)",
351 command, ret, errno);
356 int _app2sd_delete_loopback_device(const char *loopback_device)
360 ret = unlink(loopback_device);
362 if (errno == ENOENT) {
363 _W("unable to access file (%s)", loopback_device);
365 _E("unable to delete (%s)", loopback_device);
366 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
370 return APP2EXT_SUCCESS;
373 int _app2sd_create_file_system(const char *device_path)
379 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
381 if (device_path == NULL) {
383 return APP2EXT_ERROR_INVALID_ARGUMENTS;
386 /* Format the filesystem [create a filesystem]*/
387 fp = fopen(device_path, "r+");
389 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
390 _E("unable to access (%s) error is (%d, %s)",
391 device_path, errno, err_str);
392 return APP2EXT_ERROR_ACCESS_FILE;
396 ret = _xsystem(argv);
398 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
399 _E("creating file system failed, error is (%s)", err_str);
400 return APP2EXT_ERROR_CREATE_FS;
405 static int _app2sd_create_dir_with_link(const char *application_path,
406 const char *pkgid, const char *dir_name, uid_t uid)
409 char app_dir_mmc_path[FILENAME_MAX];
410 char app_dir_path[FILENAME_MAX];
412 snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
413 application_path, dir_name);
414 snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
415 application_path, dir_name);
417 ret = _app2sd_make_directory(app_dir_mmc_path, uid);
419 _E("create directory failed");
420 return APP2EXT_ERROR_CREATE_DIRECTORY;
423 ret = symlink(app_dir_mmc_path, app_dir_path);
425 if (errno == EEXIST) {
426 _D("file with symlink name present (%s)", app_dir_path);
428 _E("symbolic link creation failed, error: %d", errno);
429 return APP2EXT_ERROR_CREATE_SYMLINK;
433 return APP2EXT_SUCCESS;
436 static int _app2sd_create_directory_entry(const char *application_path,
437 const char *pkgid, GList *dir_list, uid_t uid)
441 app2ext_dir_details *dir_detail;
443 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
444 dir_detail = (app2ext_dir_details *)list->data;
445 if (dir_detail == NULL || dir_detail->name == NULL ||
446 dir_detail->type != APP2EXT_DIR_RO)
448 ret = _app2sd_create_dir_with_link(application_path,
449 pkgid, dir_detail->name, uid);
453 return APP2EXT_SUCCESS;
456 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
457 const char *dev, int mount_type, GList *dir_list,
458 app2sd_cmd cmd, uid_t uid)
462 char app_mmc_path[FILENAME_MAX];
463 char temp_path[FILENAME_MAX];
466 struct timespec time = {
468 .tv_nsec = 1000 * 1000 * 200
470 char mountflags_str[BUF_SIZE];
471 const char *argv_mount[] = { "/bin/app2sd-mount-helper", dev,
472 app_mmc_path, FS_TYPE, mountflags_str, NULL };
475 _E("input param is NULL (%s)", dev);
476 return APP2EXT_ERROR_INVALID_ARGUMENTS;
479 /* check directory existence */
480 fd = open(application_path, O_RDONLY | O_DIRECTORY);
482 _E("path(%s) error(%d)", application_path, errno);
483 return APP2EXT_ERROR_OPEN_DIR;
487 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
489 if (ret < 0 || ret > sizeof(app_mmc_path)) {
491 return APP2EXT_ERROR_OPEN_DIR;
493 fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
495 _E("path(%s) error(%d)", app_mmc_path, errno);
496 return APP2EXT_ERROR_OPEN_DIR;
500 nanosleep(&time, NULL); /* 200ms sleep */
501 _D("give a delay for mount");
503 switch (mount_type) {
505 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
506 MS_MGC_VAL | MS_RDONLY | MS_NOSUID);
507 ret = _xsystem(argv_mount);
509 _E("read only mount failed, errono is (%d), "
510 "dev is (%s) path is (%s)",
511 ret, dev, app_mmc_path);
512 ret = APP2EXT_ERROR_MOUNT;
516 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
517 MS_MGC_VAL | MS_NOSUID);
518 ret = _xsystem(argv_mount);
520 _E("read write mount failed, errno is (%d)", ret);
521 ret = APP2EXT_ERROR_MOUNT;
524 case MOUNT_TYPE_RW_NOEXEC:
525 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
526 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID);
527 ret = _xsystem(argv_mount);
529 _E("rwnx mount failed errno is (%d)", ret);
530 ret = APP2EXT_ERROR_MOUNT;
533 case MOUNT_TYPE_RD_REMOUNT:
534 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
535 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT |
537 ret = _xsystem(argv_mount);
539 _E("read remount failed errno is (%d)", ret);
540 ret = APP2EXT_ERROR_MOUNT;
543 case MOUNT_TYPE_RW_REMOUNT:
544 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
545 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID);
546 ret = _xsystem(argv_mount);
547 err_str = strerror_r(ret, err_buf, sizeof(err_buf));
549 _E("read write remount failed errno(%d), errstr(%s)",
551 ret = APP2EXT_ERROR_MOUNT;
555 _E("invalid mount type");
559 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
560 cmd == APP2SD_PRE_UPGRADE) {
561 ret = _app2sd_create_directory_entry(application_path,
562 pkgid, dir_list, uid);
565 if (mount_type != MOUNT_TYPE_RD &&
566 mount_type != MOUNT_TYPE_RD_REMOUNT) {
567 /* change lost+found permission */
568 ret = snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
570 if (ret < 0 || ret > sizeof(temp_path)) {
572 return APP2EXT_ERROR_CREATE_DIRECTORY;
574 ret = _app2sd_make_directory(temp_path, uid);
576 _E("create directory(%s) failed", temp_path);
577 return APP2EXT_ERROR_CREATE_DIRECTORY;
584 int _app2sd_unmount_app_content(const char *application_path)
587 char app_mmc_path[FILENAME_MAX];
591 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
593 ret = umount(app_mmc_path);
595 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
596 _D("unable to umount the dir, ret(%d) error(%d, %s)",
597 ret, errno, err_str);
603 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
609 ret = _app2sd_copy_dir(src_path, arch_path);
610 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
611 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
612 _E("unable to copy from (%s) to (%s), err is (%s)",
613 src_path, arch_path, err_str);
614 return APP2EXT_ERROR_MOVE;
617 ret = _app2sd_delete_directory(src_path);
619 _E("unable to delete (%s)", src_path);
620 return APP2EXT_ERROR_DELETE_DIRECTORY;
626 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
627 uid_t uid, char *mmc_path, char **image_path)
630 mode_t mode = DIR_PERMS;
631 char temp_dir_path[FILENAME_MAX];
632 char app_mmc_path[FILENAME_MAX];
633 char app_archive_path[FILENAME_MAX];
634 char application_path[FILENAME_MAX];
635 char loopback_device[FILENAME_MAX];
636 unsigned long long total_size = 0;
643 app2ext_dir_details *dir_detail;
647 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
648 loopback_device, sizeof(loopback_device));
652 _app2sd_set_application_path(pkgid, uid, application_path,
653 sizeof(application_path));
655 /* check whether application is in external memory or not */
656 fp = fopen(loopback_device, "r+");
658 _W("Already %s entry is present in the SD Card, "
659 "delete entry and go on without return", pkgid);
661 _app2sd_force_clean(pkgid, application_path, loopback_device,
665 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
667 if (ret < 0 || ret > sizeof(app_mmc_path)) {
669 return APP2EXT_ERROR_CREATE_DIRECTORY;
671 ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
673 if (ret < 0 || ret > sizeof(app_archive_path)) {
675 return APP2EXT_ERROR_CREATE_DIRECTORY;
678 ret = mkdir(app_mmc_path, mode);
680 if (errno != EEXIST) {
681 _E("unable to create directory for archiving,"
682 " error(%d)", errno);
683 return APP2EXT_ERROR_CREATE_DIRECTORY;
687 ret = mkdir(app_archive_path, mode);
689 if (errno != EEXIST) {
690 _E("unable to create directory for archiving,"
691 " error(%d)", errno);
692 return APP2EXT_ERROR_CREATE_DIRECTORY;
696 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
697 dir_detail = (app2ext_dir_details *)list->data;
698 if (dir_detail == NULL || dir_detail->name == NULL ||
699 dir_detail->type != APP2EXT_DIR_RO)
701 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
702 application_path, dir_detail->name);
703 if (ret < 0 || ret > sizeof(temp_dir_path)) {
705 return APP2EXT_ERROR_MMC_STATUS;
707 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
708 total_size += _app2sd_calculate_dir_size(temp_dir_path);
711 reqd_size = ((total_size) / (1024 * 1024)) + 2;
712 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
714 /* find avialable free memory in the MMC card */
715 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
717 _E("unable to get available free memory in MMC (%d)", ret);
718 return APP2EXT_ERROR_MMC_STATUS;
720 /* if avaialalbe free memory in MMC is less than
721 * required size + 5MB, return error
723 if (reqd_disk_size > free_mmc_mem) {
724 _E("insufficient memory in MMC for "
725 "application installation (%d)", ret);
726 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
728 /* create a loopback device */
729 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
730 (reqd_disk_size + PKG_BUF_SIZE));
732 _E("loopback node creation failed");
736 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
738 _E("dmcrypt setup device error(%d)", ret);
739 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
742 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
745 _E("dmcrypt open device error");
746 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
748 /* format the loopback file system */
749 ret = _app2sd_create_file_system(device_node);
751 _E("create ext4 filesystem failed");
752 ret = APP2EXT_ERROR_CREATE_FS;
756 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
757 dir_detail = (app2ext_dir_details *)list->data;
758 if (dir_detail == NULL || dir_detail->name == NULL ||
759 dir_detail->type != APP2EXT_DIR_RO)
761 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
762 application_path, dir_detail->name);
763 if (ret < 0 || ret > sizeof(temp_dir_path)) {
765 ret = APP2EXT_ERROR_MOVE;
768 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
769 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
771 _E("unable to copy from (%s) to (%s)",
772 temp_dir_path, app_archive_path);
777 /* mount the loopback encrypted pseudo device on
778 * application installation path as with Read Write permission
780 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
781 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
787 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
788 dir_detail = (app2ext_dir_details *)list->data;
789 if (dir_detail == NULL || dir_detail->name == NULL ||
790 dir_detail->type != APP2EXT_DIR_RO)
792 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
793 app_archive_path, dir_detail->name);
794 if (ret < 0 || ret > sizeof(temp_dir_path)) {
796 ret = APP2EXT_ERROR_COPY_DIRECTORY;
799 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
800 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
802 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
803 _E("unable to access (%s)", temp_dir_path);
805 err_str = strerror_r(errno, err_buf,
807 _E("unable to copy from (%s) to (%s),"
808 " error is (%s)", temp_dir_path,
809 app_mmc_path, err_str);
813 ret = _app2sd_delete_directory(temp_dir_path);
815 _E("unable to delete (%s)", temp_dir_path);
820 ret = _app2sd_delete_directory(app_archive_path);
822 _E("unable to delete (%s)", app_archive_path);
823 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
827 *image_path = strdup(loopback_device);
828 return APP2EXT_SUCCESS;
838 static int __check_storage_availability(
839 const char *loopback_device, int free_internal_mem) {
840 unsigned long long temp;
843 temp = _app2sd_calculate_file_size(loopback_device);
844 reqd_size = (int)((temp) / (1024 * 1024));
845 _D("reqd size is (%d)", reqd_size);
847 if (reqd_size == 0) {
848 _E("app entry is not present in SD Card");
849 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
852 _I("reqd size: (%d)MB, free internal mem: (%d)MB",
853 reqd_size, free_internal_mem);
855 /* if avaialalbe free memory in internal storage is
856 * less than required size, return error
858 if (reqd_size > free_internal_mem) {
859 _E("innsufficient memory in internal storage"
860 " for application installation");
861 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
867 static int __copy_directories(const char *app_mmc_path, const char *app_archive_path,
868 const char *application_path, app2ext_dir_details *dir_detail)
871 char temp_dir_path[FILENAME_MAX];
875 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
876 app_mmc_path, dir_detail->name);
877 if (ret < 0 || ret > sizeof(temp_dir_path)) {
881 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
882 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
884 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
885 _E("unable to access (%s)", temp_dir_path);
887 err_str = strerror_r(errno, err_buf,
889 _E("unable to copy from (%s) to (%s),"
890 "error is (%s)", temp_dir_path,
891 app_archive_path, err_str);
895 /* delete the symbolic link files [bin, lib, res]*/
896 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
897 application_path, dir_detail->name);
898 if (ret < 0 || ret > sizeof(temp_dir_path)) {
902 _D("unlink, temp_dir_path(%s)", temp_dir_path);
903 ret = unlink(temp_dir_path);
905 if (errno == ENOENT) {
906 _W("(%s) does not exist", temp_dir_path);
908 _E("unable to remove the symbolic link file "
909 "(%s), it is already unlinked",
914 /* Copy content to destination */
915 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
916 app_archive_path, dir_detail->name);
917 if (ret < 0 || ret > sizeof(temp_dir_path)) {
921 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
922 ret = _app2sd_copy_dir(temp_dir_path, application_path);
924 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
925 _E("unable to access (%s)", temp_dir_path);
927 err_str = strerror_r(errno, err_buf,
929 _E("unable to copy from (%s) to (%s), "
930 "error is (%s)", temp_dir_path,
931 application_path, err_str);
938 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
939 uid_t uid, char *mmc_path)
942 mode_t mode = DIR_PERMS;
943 char app_mmc_path[FILENAME_MAX];
944 char app_archive_path[FILENAME_MAX];
945 char application_path[FILENAME_MAX];
946 char loopback_device[FILENAME_MAX];
950 app2ext_dir_details *dir_detail;
951 int free_internal_mem;
954 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
955 loopback_device, sizeof(loopback_device));
959 _app2sd_set_application_path(pkgid, uid, application_path,
960 sizeof(application_path));
962 /* check whether application is in external memory or not */
963 fp = fopen(loopback_device, "r+");
965 _E("application (%s) is not installed on SD Card",
967 return APP2EXT_ERROR_FILE_ABSENT;
971 /* find avialable free memory in the internal storage */
972 ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
975 _E("unable to get available free memory in internal (%d)", ret);
976 return APP2EXT_ERROR_MMC_STATUS;
979 fp = fopen(loopback_device, "r+");
981 _E("app entry is not present in SD card");
982 return APP2EXT_ERROR_INVALID_PACKAGE;
986 /* get installed app size*/
987 ret = __check_storage_availability(loopback_device, free_internal_mem);
992 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
993 if (device_node == NULL) {
994 /* do loopback setup */
995 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
996 false, uid, &device_node);
998 _E("dmcrypt open device error(%d)", ret);
999 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1001 mount_type = MOUNT_TYPE_RW;
1003 mount_type = MOUNT_TYPE_RW_REMOUNT;
1006 ret = _app2sd_mount_app_content(application_path,
1007 pkgid, device_node, mount_type,
1008 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1011 ret = APP2EXT_ERROR_MOUNT_PATH;
1015 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
1017 if (ret < 0 || ret > sizeof(app_mmc_path)) {
1018 _E("snprintf fail");
1022 ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
1024 if (ret < 0 || ret > sizeof(app_archive_path)) {
1025 _E("snprintf fail");
1030 ret = mkdir(app_archive_path, mode);
1032 if (errno != EEXIST) {
1033 _E("unable to create directory for archiving,"
1034 " error(%d)", errno);
1035 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
1040 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1041 dir_detail = (app2ext_dir_details *)list->data;
1042 if (dir_detail == NULL || dir_detail->name == NULL ||
1043 dir_detail->type != APP2EXT_DIR_RO)
1045 /* archiving code */
1046 ret = __copy_directories(app_mmc_path, app_archive_path,
1047 application_path, dir_detail);
1054 _D("copying file completed");
1055 ret = _app2sd_unmount_app_content(application_path);
1057 _E("unable to unmount SD directory for app (%s)", pkgid);
1059 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1061 _E("close dmcrypt device error(%d)", ret);
1063 ret = _app2sd_delete_loopback_device(loopback_device);
1065 _E("unable to delete the loopback device for (%s)", pkgid);
1067 ret = _app2sd_delete_directory(app_mmc_path);
1069 _E("unable to delete (%s)", app_mmc_path);
1071 ret = _app2sd_delete_directory(app_archive_path);
1073 _E("unable to delete (%s)", app_archive_path);
1075 /* remove passwrd from DB */
1076 ret = _app2sd_initialize_db();
1078 _E("app2sd db initialize failed");
1080 ret = _app2sd_remove_info_from_db(pkgid, uid);
1082 _E("cannot remove info from db");
1084 return APP2EXT_SUCCESS;
1093 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1094 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
1098 switch (move_type) {
1099 case APP2EXT_MOVE_TO_EXT:
1100 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1101 uid, mmc_path, image_path);
1103 _E("move app to external memory failed(%d)", ret);
1107 case APP2EXT_MOVE_TO_PHONE:
1108 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1111 _E("move app to internal memory failed(%d)", ret);
1116 _E("invalid argument");
1117 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1123 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1125 char path[FILENAME_MAX];
1128 app2ext_dir_details *dir_detail;
1130 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1131 dir_detail = (app2ext_dir_details *)list->data;
1132 if (dir_detail == NULL || dir_detail->name == NULL ||
1133 dir_detail->type != APP2EXT_DIR_RO)
1136 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1137 ret = _app2sd_copy_dir(path, dest);
1139 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1140 _E("unable to access (%s)", path);
1142 _E("unable to copy from (%s) "
1143 "to (%s), errno is (%d)",
1145 return APP2EXT_ERROR_MOVE;
1150 return APP2EXT_SUCCESS;
1153 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1154 const char *temp_pkgid, const char *temp_application_path,
1155 const char *temp_loopback_device, GList *dir_list,
1156 char *dev_node, int size, uid_t uid)
1161 /* create a new loopback device */
1162 ret = _app2sd_create_loopback_device(temp_pkgid,
1163 temp_loopback_device, (size + PKG_BUF_SIZE));
1165 _E("package already present");
1169 /* perform loopback encryption setup */
1170 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1171 temp_loopback_device, uid);
1173 _E("dmcrypt duplicate encryption setup failed");
1174 _app2sd_delete_loopback_device(temp_loopback_device);
1175 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1178 /* format the loopback file system */
1179 ret = _app2sd_create_file_system(dev_node);
1181 _E("creating fs failed");
1182 err_res = APP2EXT_ERROR_CREATE_FS;
1185 _D("create filesystem SUCCESS");
1187 /* do mounting for new dev*/
1188 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1189 dev_node, MOUNT_TYPE_RW, dir_list,
1190 APP2SD_PRE_UPGRADE, uid);
1192 _E("remount failed");
1193 err_res = APP2EXT_ERROR_MOUNT_PATH;
1197 return APP2EXT_SUCCESS;
1201 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1203 _E("close dmcrypt device error(%d)", ret);
1204 _app2sd_delete_loopback_device(temp_loopback_device);
1211 int _app2sd_update_loopback_device_size(const char *pkgid,
1212 const char *loopback_device, const char *application_path,
1213 const char *temp_pkgid, const char *temp_loopback_device,
1214 const char *temp_application_path, int size, GList *dir_list,
1218 char *old_device_node;
1220 char app_mmc_path[FILENAME_MAX];
1221 char temp_app_mmc_path[FILENAME_MAX];
1224 ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1225 temp_application_path, temp_loopback_device,
1226 dir_list, NULL, size, uid);
1228 _E("creating duplicate device failed");
1232 /* get the associated device node for SD card applicatione */
1234 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1235 if (old_device_node == NULL) {
1236 /* do loopback setup */
1237 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1238 false, uid, &old_device_node);
1240 _E("dmcrypt open device error");
1241 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1244 mount_type = MOUNT_TYPE_RW;
1246 mount_type = MOUNT_TYPE_RW_REMOUNT;
1250 ret = _app2sd_mount_app_content(application_path, pkgid,
1251 old_device_node, mount_type, dir_list,
1252 APP2SD_PRE_UPGRADE, uid);
1254 _E("remount failed");
1255 err_res = APP2EXT_ERROR_MOUNT_PATH;
1257 free(old_device_node);
1259 snprintf(app_mmc_path, sizeof(app_mmc_path),
1260 "%s/.mmc", application_path);
1261 snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1262 "%s/.mmc", temp_application_path);
1264 ret = _app2sd_copy_ro_content(app_mmc_path,
1265 temp_app_mmc_path, dir_list);
1267 _E("copy ro content failed");
1271 ret = _app2sd_unmount_app_content(application_path);
1273 _E("unable to unmount the SD application");
1274 err_res = APP2EXT_ERROR_UNMOUNT;
1277 ret = _app2sd_unmount_app_content(temp_application_path);
1279 _E("unable to unmount the SD application");
1280 err_res = APP2EXT_ERROR_UNMOUNT;
1284 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1286 _E("close dmcrypt device error(%d)", ret);
1287 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1291 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1293 _E("close dmcrypt device error(%d)", ret);
1294 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1298 ret = _app2sd_delete_directory(loopback_device);
1300 _E("unable to delete (%s)", loopback_device);
1301 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1305 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1307 _E("unable to rename (%s)", temp_loopback_device);
1308 err_res = APP2EXT_ERROR_MOVE;
1312 ret = _app2sd_delete_directory(temp_application_path);
1314 _E("unable to delete (%s)", temp_application_path);
1315 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1319 return APP2EXT_SUCCESS;
1322 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1324 _E("close dmcrypt device error(%d)", ret);
1326 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1328 _E("close dmcrypt device error(%d)", ret);
1330 _app2sd_delete_loopback_device(temp_loopback_device);
1332 ret = _app2sd_delete_directory(temp_application_path);
1334 _E("unable to delete (%s)", temp_application_path);
1339 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1340 const char *loopback_device, uid_t uid)
1344 /* unmount the loopback encrypted pseudo device from
1345 * the application installation path
1347 ret = _app2sd_unmount_app_content(application_path);
1349 _W("unable to unmount the app content (%d)", ret);
1351 /* detach the loopback encryption setup for the application */
1352 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1354 _W("close dmcrypt device error (%d)", ret);
1356 /* delete the loopback device from the SD card */
1357 ret = _app2sd_delete_loopback_device(loopback_device);
1359 _W("unable to detach the loopback encryption setup for "
1362 /* delete symlink */
1363 _app2sd_delete_symlink(application_path);
1365 /* remove passwrd from DB */
1366 ret = _app2sd_initialize_db();
1368 _W("app2sd db initialize failed");
1370 ret = _app2sd_remove_info_from_db(pkgid, uid);
1372 _W("cannot remove info from db");