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 "
136 passwd, DMCRYPT_ITER_TIME, DMCRYPT_KEY_LEN,
138 memset(passwd, 0, strlen(passwd));
140 ret = system(dmcrypt_setup_cmd);
141 memset(dmcrypt_setup_cmd, 0, BUF_SIZE);
143 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
144 _E("Error setting up dmcrypt on app2sd file, error:%s, ret:%d",
146 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
152 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
153 bool is_dup, uid_t uid, char **dev_node)
158 char dmcrypt_open_cmd[BUF_SIZE];
159 char dev_name[BUF_SIZE];
163 if (pkgid == NULL || loopback_device == NULL) {
164 _E("invalid argument");
165 return APP2EXT_ERROR_INVALID_ARGUMENTS;
169 snprintf(dev_name, sizeof(dev_name), "%s.new_%d", pkgid, uid);
171 snprintf(dev_name, sizeof(dev_name), "%s_%d", pkgid, uid);
173 /* get password for dmcrypt encryption */
174 ret = _app2sd_initialize_db();
176 _E("app2sd db initialize failed");
177 return APP2EXT_ERROR_DB_INITIALIZE;
180 passwd = _app2sd_get_password_from_db(pkgid, uid);
181 if (passwd == NULL) {
182 _E("no password found for [%s]", pkgid);
183 return APP2EXT_ERROR_SQLITE_REGISTRY;
186 if (_app2sd_check_is_luks_device(loopback_device) == 0) {
187 _W("legacy image format!");
188 ret = snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
189 "/bin/echo '%s' | /sbin/cryptsetup "
190 "-M plain -c aes-cbc-plain -h plain open %s %s",
191 passwd, loopback_device, dev_name);
192 if (ret < 0 || ret > sizeof(dmcrypt_open_cmd)) {
194 _E("snprintf fail\n");
198 ret = snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
199 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen "
201 passwd, loopback_device, dev_name);
202 if (ret < 0 || ret > sizeof(dmcrypt_open_cmd)) {
203 _E("snprintf fail\n");
210 ret = system(dmcrypt_open_cmd);
212 err_str = strerror_r(errno, buf, sizeof(buf));
213 _E("error opening dmcrypt device, error: [%s]", err_str);
214 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
217 size = strlen("/dev/mapper/%s") + strlen(dev_name) + 1;
218 *dev_node = (char *)malloc(size);
219 if (*dev_node == NULL) {
220 _E("memory alloc failed");
221 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
223 ret = snprintf(*dev_node, size, "/dev/mapper/%s", dev_name);
224 if (ret < 0 || ret > size) {
225 _E("snprintf fail\n");
233 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
236 char dev_node[BUF_SIZE];
237 char dmcrypt_close_cmd[BUF_SIZE];
238 char err_buf[BUF_SIZE];
243 _E("invalid argument");
244 return APP2EXT_ERROR_INVALID_ARGUMENTS;
247 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
249 _W("no associated device node(%s_%d) found", pkgid, uid);
250 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
255 ret = snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
256 if (ret < 0 || ret > sizeof(dev_node)) {
258 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
260 ret = snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
261 "/sbin/cryptsetup -q luksClose %s", dev_node);
262 if (ret < 0 || ret > sizeof(dmcrypt_close_cmd)) {
264 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
266 ret = system(dmcrypt_close_cmd);
268 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
269 _E("error closing dmcrypt on app2sd file: %s", err_str);
270 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
276 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
281 snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
282 if (access(buf, F_OK) == 0) {
283 dev_node = strdup(buf);
284 if (dev_node == NULL) {
285 _E("memory alloc failed");
288 _D("device_node: (%s)", dev_node);
291 _D("can not access dev_node(%s), errno(%d)", buf, errno);
296 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
297 const char *temp_loopback_device, uid_t uid)
302 if (pkgid == NULL || temp_loopback_device == NULL) {
303 _E("invalid argument");
307 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
310 _E("dmcrypt setup device error(%d)", ret);
314 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
317 _E("dmcrypt open device error");
324 int _app2sd_create_loopback_device(const char *pkgid,
325 const char *loopback_device, int size)
328 char command[FILENAME_MAX];
331 const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
332 "bs=1M", buff, NULL };
334 if (pkgid == NULL || size <= 0) {
335 _E("invalid argument");
336 return APP2EXT_ERROR_INVALID_ARGUMENTS;
339 fp = fopen(loopback_device, "r+");
341 _W("encrypted file already exists (%s)", loopback_device);
343 return APP2EXT_ERROR_PKG_EXISTS;
346 snprintf(command, sizeof(command), "of=%s", loopback_device);
347 snprintf(buff, sizeof(buff), "count=%d", size);
349 ret = _xsystem(argv);
351 _E("command (%s) failed, ret(%d), errno(%d)",
352 command, ret, errno);
357 int _app2sd_delete_loopback_device(const char *loopback_device)
361 ret = unlink(loopback_device);
363 if (errno == ENOENT) {
364 _W("unable to access file (%s)", loopback_device);
366 _E("unable to delete (%s)", loopback_device);
367 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
371 return APP2EXT_SUCCESS;
374 int _app2sd_create_file_system(const char *device_path)
380 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
382 if (device_path == NULL) {
384 return APP2EXT_ERROR_INVALID_ARGUMENTS;
387 /* Format the filesystem [create a filesystem]*/
388 fp = fopen(device_path, "r+");
390 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
391 _E("unable to access (%s) error is (%d, %s)",
392 device_path, errno, err_str);
393 return APP2EXT_ERROR_ACCESS_FILE;
397 ret = _xsystem(argv);
399 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
400 _E("creating file system failed, error is (%s)", err_str);
401 return APP2EXT_ERROR_CREATE_FS;
406 static int _app2sd_create_dir_with_link(const char *application_path,
407 const char *pkgid, const char *dir_name, uid_t uid)
410 char app_dir_mmc_path[FILENAME_MAX];
411 char app_dir_path[FILENAME_MAX];
413 snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
414 application_path, dir_name);
415 snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
416 application_path, dir_name);
418 ret = _app2sd_make_directory(app_dir_mmc_path, uid);
420 _E("create directory failed");
421 return APP2EXT_ERROR_CREATE_DIRECTORY;
424 ret = symlink(app_dir_mmc_path, app_dir_path);
426 if (errno == EEXIST) {
427 _D("file with symlink name present (%s)", app_dir_path);
429 _E("symbolic link creation failed, error: %d", errno);
430 return APP2EXT_ERROR_CREATE_SYMLINK;
434 return APP2EXT_SUCCESS;
437 static int _app2sd_create_directory_entry(const char *application_path,
438 const char *pkgid, GList *dir_list, uid_t uid)
442 app2ext_dir_details *dir_detail;
444 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
445 dir_detail = (app2ext_dir_details *)list->data;
446 if (dir_detail == NULL || dir_detail->name == NULL ||
447 dir_detail->type != APP2EXT_DIR_RO)
449 ret = _app2sd_create_dir_with_link(application_path,
450 pkgid, dir_detail->name, uid);
454 return APP2EXT_SUCCESS;
457 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
458 const char *dev, int mount_type, GList *dir_list,
459 app2sd_cmd cmd, uid_t uid)
463 char app_mmc_path[FILENAME_MAX];
464 char temp_path[FILENAME_MAX];
467 struct timespec time = {
469 .tv_nsec = 1000 * 1000 * 200
471 char mountflags_str[BUF_SIZE];
472 const char *argv_mount[] = { "/bin/app2sd-mount-helper", dev,
473 app_mmc_path, FS_TYPE, mountflags_str, NULL };
476 _E("input param is NULL (%s)", dev);
477 return APP2EXT_ERROR_INVALID_ARGUMENTS;
480 /* check directory existence */
481 fd = open(application_path, O_RDONLY | O_DIRECTORY);
483 _E("path(%s) error(%d)", application_path, errno);
484 return APP2EXT_ERROR_OPEN_DIR;
488 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
490 if (ret < 0 || ret > sizeof(app_mmc_path)) {
492 return APP2EXT_ERROR_OPEN_DIR;
494 fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
496 _E("path(%s) error(%d)", app_mmc_path, errno);
497 return APP2EXT_ERROR_OPEN_DIR;
501 nanosleep(&time, NULL); /* 200ms sleep */
502 _D("give a delay for mount");
504 switch (mount_type) {
506 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
507 MS_MGC_VAL | MS_RDONLY | MS_NOSUID);
508 ret = _xsystem(argv_mount);
510 _E("read only mount failed, errono is (%d), "
511 "dev is (%s) path is (%s)",
512 ret, dev, app_mmc_path);
513 ret = APP2EXT_ERROR_MOUNT;
517 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
518 MS_MGC_VAL | MS_NOSUID);
519 ret = _xsystem(argv_mount);
521 _E("read write mount failed, errno is (%d)", ret);
522 ret = APP2EXT_ERROR_MOUNT;
525 case MOUNT_TYPE_RW_NOEXEC:
526 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
527 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID);
528 ret = _xsystem(argv_mount);
530 _E("rwnx mount failed errno is (%d)", ret);
531 ret = APP2EXT_ERROR_MOUNT;
534 case MOUNT_TYPE_RD_REMOUNT:
535 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
536 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT |
538 ret = _xsystem(argv_mount);
540 _E("read remount failed errno is (%d)", ret);
541 ret = APP2EXT_ERROR_MOUNT;
544 case MOUNT_TYPE_RW_REMOUNT:
545 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
546 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID);
547 ret = _xsystem(argv_mount);
548 err_str = strerror_r(ret, err_buf, sizeof(err_buf));
550 _E("read write remount failed errno(%d), errstr(%s)",
552 ret = APP2EXT_ERROR_MOUNT;
556 _E("invalid mount type");
560 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
561 cmd == APP2SD_PRE_UPGRADE) {
562 ret = _app2sd_create_directory_entry(application_path,
563 pkgid, dir_list, uid);
566 if (mount_type != MOUNT_TYPE_RD &&
567 mount_type != MOUNT_TYPE_RD_REMOUNT) {
568 /* change lost+found permission */
569 ret = snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
571 if (ret < 0 || ret > sizeof(temp_path)) {
573 return APP2EXT_ERROR_CREATE_DIRECTORY;
575 ret = _app2sd_make_directory(temp_path, uid);
577 _E("create directory(%s) failed", temp_path);
578 return APP2EXT_ERROR_CREATE_DIRECTORY;
585 int _app2sd_unmount_app_content(const char *application_path)
588 char app_mmc_path[FILENAME_MAX];
592 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
594 ret = umount(app_mmc_path);
596 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
597 _D("unable to umount the dir, ret(%d) error(%d, %s)",
598 ret, errno, err_str);
604 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
610 ret = _app2sd_copy_dir(src_path, arch_path);
611 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
612 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
613 _E("unable to copy from (%s) to (%s), err is (%s)",
614 src_path, arch_path, err_str);
615 return APP2EXT_ERROR_MOVE;
618 ret = _app2sd_delete_directory(src_path);
620 _E("unable to delete (%s)", src_path);
621 return APP2EXT_ERROR_DELETE_DIRECTORY;
627 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
628 uid_t uid, char *mmc_path, char **image_path)
631 mode_t mode = DIR_PERMS;
632 char temp_dir_path[FILENAME_MAX];
633 char app_mmc_path[FILENAME_MAX];
634 char app_archive_path[FILENAME_MAX];
635 char application_path[FILENAME_MAX];
636 char loopback_device[FILENAME_MAX];
637 unsigned long long total_size = 0;
644 app2ext_dir_details *dir_detail;
648 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
649 loopback_device, sizeof(loopback_device));
653 _app2sd_set_application_path(pkgid, uid, application_path,
654 sizeof(application_path));
656 /* check whether application is in external memory or not */
657 fp = fopen(loopback_device, "r+");
659 _W("Already %s entry is present in the SD Card, "
660 "delete entry and go on without return", pkgid);
662 _app2sd_force_clean(pkgid, application_path, loopback_device,
666 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
668 if (ret < 0 || ret > sizeof(app_mmc_path)) {
670 return APP2EXT_ERROR_CREATE_DIRECTORY;
672 ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
674 if (ret < 0 || ret > sizeof(app_archive_path)) {
676 return APP2EXT_ERROR_CREATE_DIRECTORY;
679 ret = mkdir(app_mmc_path, mode);
681 if (errno != EEXIST) {
682 _E("unable to create directory for archiving,"
683 " error(%d)", errno);
684 return APP2EXT_ERROR_CREATE_DIRECTORY;
688 ret = mkdir(app_archive_path, mode);
690 if (errno != EEXIST) {
691 _E("unable to create directory for archiving,"
692 " error(%d)", errno);
693 return APP2EXT_ERROR_CREATE_DIRECTORY;
697 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
698 dir_detail = (app2ext_dir_details *)list->data;
699 if (dir_detail == NULL || dir_detail->name == NULL ||
700 dir_detail->type != APP2EXT_DIR_RO)
702 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
703 application_path, dir_detail->name);
704 if (ret < 0 || ret > sizeof(temp_dir_path)) {
706 return APP2EXT_ERROR_MMC_STATUS;
708 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
709 total_size += _app2sd_calculate_dir_size(temp_dir_path);
712 reqd_size = ((total_size) / (1024 * 1024)) + 2;
713 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
715 /* find avialable free memory in the MMC card */
716 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
718 _E("unable to get available free memory in MMC (%d)", ret);
719 return APP2EXT_ERROR_MMC_STATUS;
721 /* if avaialalbe free memory in MMC is less than
722 * required size + 5MB, return error
724 if (reqd_disk_size > free_mmc_mem) {
725 _E("insufficient memory in MMC for "
726 "application installation (%d)", ret);
727 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
729 /* create a loopback device */
730 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
731 (reqd_disk_size + PKG_BUF_SIZE));
733 _E("loopback node creation failed");
737 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
739 _E("dmcrypt setup device error(%d)", ret);
740 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
743 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
746 _E("dmcrypt open device error");
747 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
749 /* format the loopback file system */
750 ret = _app2sd_create_file_system(device_node);
752 _E("create ext4 filesystem failed");
753 ret = APP2EXT_ERROR_CREATE_FS;
757 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
758 dir_detail = (app2ext_dir_details *)list->data;
759 if (dir_detail == NULL || dir_detail->name == NULL ||
760 dir_detail->type != APP2EXT_DIR_RO)
762 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
763 application_path, dir_detail->name);
764 if (ret < 0 || ret > sizeof(temp_dir_path)) {
766 ret = APP2EXT_ERROR_MOVE;
769 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
770 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
772 _E("unable to copy from (%s) to (%s)",
773 temp_dir_path, app_archive_path);
778 /* mount the loopback encrypted pseudo device on
779 * application installation path as with Read Write permission
781 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
782 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
788 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
789 dir_detail = (app2ext_dir_details *)list->data;
790 if (dir_detail == NULL || dir_detail->name == NULL ||
791 dir_detail->type != APP2EXT_DIR_RO)
793 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
794 app_archive_path, dir_detail->name);
795 if (ret < 0 || ret > sizeof(temp_dir_path)) {
797 ret = APP2EXT_ERROR_COPY_DIRECTORY;
800 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
801 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
803 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
804 _E("unable to access (%s)", temp_dir_path);
806 err_str = strerror_r(errno, err_buf,
808 _E("unable to copy from (%s) to (%s),"
809 " error is (%s)", temp_dir_path,
810 app_mmc_path, err_str);
814 ret = _app2sd_delete_directory(temp_dir_path);
816 _E("unable to delete (%s)", temp_dir_path);
821 ret = _app2sd_delete_directory(app_archive_path);
823 _E("unable to delete (%s)", app_archive_path);
824 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
828 *image_path = strdup(loopback_device);
829 return APP2EXT_SUCCESS;
839 static int __check_storage_availability(
840 const char *loopback_device, int free_internal_mem) {
841 unsigned long long temp;
844 temp = _app2sd_calculate_file_size(loopback_device);
845 reqd_size = (int)((temp) / (1024 * 1024));
846 _D("reqd size is (%d)", reqd_size);
848 if (reqd_size == 0) {
849 _E("app entry is not present in SD Card");
850 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
853 _I("reqd size: (%d)MB, free internal mem: (%d)MB",
854 reqd_size, free_internal_mem);
856 /* if avaialalbe free memory in internal storage is
857 * less than required size, return error
859 if (reqd_size > free_internal_mem) {
860 _E("innsufficient memory in internal storage"
861 " for application installation");
862 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
868 static int __copy_directories(const char *app_mmc_path, const char *app_archive_path,
869 const char *application_path, app2ext_dir_details *dir_detail)
872 char temp_dir_path[FILENAME_MAX];
876 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
877 app_mmc_path, dir_detail->name);
878 if (ret < 0 || ret > sizeof(temp_dir_path)) {
882 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
883 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
885 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
886 _E("unable to access (%s)", temp_dir_path);
888 err_str = strerror_r(errno, err_buf,
890 _E("unable to copy from (%s) to (%s),"
891 "error is (%s)", temp_dir_path,
892 app_archive_path, err_str);
896 /* delete the symbolic link files [bin, lib, res]*/
897 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
898 application_path, dir_detail->name);
899 if (ret < 0 || ret > sizeof(temp_dir_path)) {
903 _D("unlink, temp_dir_path(%s)", temp_dir_path);
904 ret = unlink(temp_dir_path);
906 if (errno == ENOENT) {
907 _W("(%s) does not exist", temp_dir_path);
909 _E("unable to remove the symbolic link file "
910 "(%s), it is already unlinked",
915 /* Copy content to destination */
916 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
917 app_archive_path, dir_detail->name);
918 if (ret < 0 || ret > sizeof(temp_dir_path)) {
922 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
923 ret = _app2sd_copy_dir(temp_dir_path, application_path);
925 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
926 _E("unable to access (%s)", temp_dir_path);
928 err_str = strerror_r(errno, err_buf,
930 _E("unable to copy from (%s) to (%s), "
931 "error is (%s)", temp_dir_path,
932 application_path, err_str);
939 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
940 uid_t uid, char *mmc_path)
943 mode_t mode = DIR_PERMS;
944 char app_mmc_path[FILENAME_MAX];
945 char app_archive_path[FILENAME_MAX];
946 char application_path[FILENAME_MAX];
947 char loopback_device[FILENAME_MAX];
951 app2ext_dir_details *dir_detail;
952 int free_internal_mem;
955 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
956 loopback_device, sizeof(loopback_device));
960 _app2sd_set_application_path(pkgid, uid, application_path,
961 sizeof(application_path));
963 /* check whether application is in external memory or not */
964 fp = fopen(loopback_device, "r+");
966 _E("application (%s) is not installed on SD Card",
968 return APP2EXT_ERROR_FILE_ABSENT;
972 /* find avialable free memory in the internal storage */
973 ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
976 _E("unable to get available free memory in internal (%d)", ret);
977 return APP2EXT_ERROR_MMC_STATUS;
980 fp = fopen(loopback_device, "r+");
982 _E("app entry is not present in SD card");
983 return APP2EXT_ERROR_INVALID_PACKAGE;
987 /* get installed app size*/
988 ret = __check_storage_availability(loopback_device, free_internal_mem);
993 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
994 if (device_node == NULL) {
995 /* do loopback setup */
996 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
997 false, uid, &device_node);
999 _E("dmcrypt open device error(%d)", ret);
1000 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1002 mount_type = MOUNT_TYPE_RW;
1004 mount_type = MOUNT_TYPE_RW_REMOUNT;
1007 ret = _app2sd_mount_app_content(application_path,
1008 pkgid, device_node, mount_type,
1009 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
1012 ret = APP2EXT_ERROR_MOUNT_PATH;
1016 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
1018 if (ret < 0 || ret > sizeof(app_mmc_path)) {
1019 _E("snprintf fail");
1023 ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
1025 if (ret < 0 || ret > sizeof(app_archive_path)) {
1026 _E("snprintf fail");
1031 ret = mkdir(app_archive_path, mode);
1033 if (errno != EEXIST) {
1034 _E("unable to create directory for archiving,"
1035 " error(%d)", errno);
1036 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
1041 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1042 dir_detail = (app2ext_dir_details *)list->data;
1043 if (dir_detail == NULL || dir_detail->name == NULL ||
1044 dir_detail->type != APP2EXT_DIR_RO)
1046 /* archiving code */
1047 ret = __copy_directories(app_mmc_path, app_archive_path,
1048 application_path, dir_detail);
1055 _D("copying file completed");
1056 ret = _app2sd_unmount_app_content(application_path);
1058 _E("unable to unmount SD directory for app (%s)", pkgid);
1060 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1062 _E("close dmcrypt device error(%d)", ret);
1064 ret = _app2sd_delete_loopback_device(loopback_device);
1066 _E("unable to delete the loopback device for (%s)", pkgid);
1068 ret = _app2sd_delete_directory(app_mmc_path);
1070 _E("unable to delete (%s)", app_mmc_path);
1072 ret = _app2sd_delete_directory(app_archive_path);
1074 _E("unable to delete (%s)", app_archive_path);
1076 /* remove passwrd from DB */
1077 ret = _app2sd_initialize_db();
1079 _E("app2sd db initialize failed");
1081 ret = _app2sd_remove_info_from_db(pkgid, uid);
1083 _E("cannot remove info from db");
1085 return APP2EXT_SUCCESS;
1094 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1095 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
1099 switch (move_type) {
1100 case APP2EXT_MOVE_TO_EXT:
1101 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1102 uid, mmc_path, image_path);
1104 _E("move app to external memory failed(%d)", ret);
1108 case APP2EXT_MOVE_TO_PHONE:
1109 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1112 _E("move app to internal memory failed(%d)", ret);
1117 _E("invalid argument");
1118 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1124 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1126 char path[FILENAME_MAX];
1129 app2ext_dir_details *dir_detail;
1131 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1132 dir_detail = (app2ext_dir_details *)list->data;
1133 if (dir_detail == NULL || dir_detail->name == NULL ||
1134 dir_detail->type != APP2EXT_DIR_RO)
1137 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1138 ret = _app2sd_copy_dir(path, dest);
1140 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1141 _E("unable to access (%s)", path);
1143 _E("unable to copy from (%s) "
1144 "to (%s), errno is (%d)",
1146 return APP2EXT_ERROR_MOVE;
1151 return APP2EXT_SUCCESS;
1154 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1155 const char *temp_pkgid, const char *temp_application_path,
1156 const char *temp_loopback_device, GList *dir_list,
1157 char *dev_node, int size, uid_t uid)
1162 /* create a new loopback device */
1163 ret = _app2sd_create_loopback_device(temp_pkgid,
1164 temp_loopback_device, (size + PKG_BUF_SIZE));
1166 _E("package already present");
1170 /* perform loopback encryption setup */
1171 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1172 temp_loopback_device, uid);
1174 _E("dmcrypt duplicate encryption setup failed");
1175 _app2sd_delete_loopback_device(temp_loopback_device);
1176 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1179 /* format the loopback file system */
1180 ret = _app2sd_create_file_system(dev_node);
1182 _E("creating fs failed");
1183 err_res = APP2EXT_ERROR_CREATE_FS;
1186 _D("create filesystem SUCCESS");
1188 /* do mounting for new dev*/
1189 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1190 dev_node, MOUNT_TYPE_RW, dir_list,
1191 APP2SD_PRE_UPGRADE, uid);
1193 _E("remount failed");
1194 err_res = APP2EXT_ERROR_MOUNT_PATH;
1198 return APP2EXT_SUCCESS;
1202 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1204 _E("close dmcrypt device error(%d)", ret);
1205 _app2sd_delete_loopback_device(temp_loopback_device);
1212 int _app2sd_update_loopback_device_size(const char *pkgid,
1213 const char *loopback_device, const char *application_path,
1214 const char *temp_pkgid, const char *temp_loopback_device,
1215 const char *temp_application_path, int size, GList *dir_list,
1219 char *old_device_node;
1221 char app_mmc_path[FILENAME_MAX];
1222 char temp_app_mmc_path[FILENAME_MAX];
1225 ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1226 temp_application_path, temp_loopback_device,
1227 dir_list, NULL, size, uid);
1229 _E("creating duplicate device failed");
1233 /* get the associated device node for SD card applicatione */
1235 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1236 if (old_device_node == NULL) {
1237 /* do loopback setup */
1238 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1239 false, uid, &old_device_node);
1241 _E("dmcrypt open device error");
1242 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1245 mount_type = MOUNT_TYPE_RW;
1247 mount_type = MOUNT_TYPE_RW_REMOUNT;
1251 ret = _app2sd_mount_app_content(application_path, pkgid,
1252 old_device_node, mount_type, dir_list,
1253 APP2SD_PRE_UPGRADE, uid);
1255 _E("remount failed");
1256 err_res = APP2EXT_ERROR_MOUNT_PATH;
1258 free(old_device_node);
1260 snprintf(app_mmc_path, sizeof(app_mmc_path),
1261 "%s/.mmc", application_path);
1262 snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1263 "%s/.mmc", temp_application_path);
1265 ret = _app2sd_copy_ro_content(app_mmc_path,
1266 temp_app_mmc_path, dir_list);
1268 _E("copy ro content failed");
1272 ret = _app2sd_unmount_app_content(application_path);
1274 _E("unable to unmount the SD application");
1275 err_res = APP2EXT_ERROR_UNMOUNT;
1278 ret = _app2sd_unmount_app_content(temp_application_path);
1280 _E("unable to unmount the SD application");
1281 err_res = APP2EXT_ERROR_UNMOUNT;
1285 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1287 _E("close dmcrypt device error(%d)", ret);
1288 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1292 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1294 _E("close dmcrypt device error(%d)", ret);
1295 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1299 ret = _app2sd_delete_directory(loopback_device);
1301 _E("unable to delete (%s)", loopback_device);
1302 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1306 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1308 _E("unable to rename (%s)", temp_loopback_device);
1309 err_res = APP2EXT_ERROR_MOVE;
1313 ret = _app2sd_delete_directory(temp_application_path);
1315 _E("unable to delete (%s)", temp_application_path);
1316 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1320 return APP2EXT_SUCCESS;
1323 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1325 _E("close dmcrypt device error(%d)", ret);
1327 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1329 _E("close dmcrypt device error(%d)", ret);
1331 _app2sd_delete_loopback_device(temp_loopback_device);
1333 ret = _app2sd_delete_directory(temp_application_path);
1335 _E("unable to delete (%s)", temp_application_path);
1340 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1341 const char *loopback_device, uid_t uid)
1345 /* unmount the loopback encrypted pseudo device from
1346 * the application installation path
1348 ret = _app2sd_unmount_app_content(application_path);
1350 _W("unable to unmount the app content (%d)", ret);
1352 /* detach the loopback encryption setup for the application */
1353 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1355 _W("close dmcrypt device error (%d)", ret);
1357 /* delete the loopback device from the SD card */
1358 ret = _app2sd_delete_loopback_device(loopback_device);
1360 _W("unable to detach the loopback encryption setup for "
1363 /* delete symlink */
1364 _app2sd_delete_symlink(application_path);
1366 /* remove passwrd from DB */
1367 ret = _app2sd_initialize_db();
1369 _W("app2sd db initialize failed");
1371 ret = _app2sd_remove_info_from_db(pkgid, uid);
1373 _W("cannot remove info from db");