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 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);
192 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
193 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen "
195 passwd, loopback_device, dev_name);
199 ret = system(dmcrypt_open_cmd);
201 err_str = strerror_r(errno, buf, sizeof(buf));
202 _E("error opening dmcrypt device, error: [%s]", err_str);
203 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
206 size = strlen("/dev/mapper/%s") + strlen(dev_name) + 1;
207 *dev_node = (char *)malloc(size);
208 if (*dev_node == NULL) {
209 _E("memory alloc failed");
210 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
212 snprintf(*dev_node, size, "/dev/mapper/%s", dev_name);
217 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
220 char dev_node[BUF_SIZE];
221 char dmcrypt_close_cmd[BUF_SIZE];
222 char err_buf[BUF_SIZE];
227 _E("invalid argument");
228 return APP2EXT_ERROR_INVALID_ARGUMENTS;
231 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
233 _W("no associated device node(%s_%d) found", pkgid, uid);
234 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
239 snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
240 snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
241 "/sbin/cryptsetup -q luksClose %s", dev_node);
242 ret = system(dmcrypt_close_cmd);
244 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
245 _E("error closing dmcrypt on app2sd file: %s", err_str);
246 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
252 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
257 snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
258 if (access(buf, F_OK) == 0) {
259 dev_node = strdup(buf);
260 if (dev_node == NULL) {
261 _E("memory alloc failed");
264 _D("device_node: (%s)", dev_node);
267 _D("can not access dev_node(%s), errno(%d)", buf, errno);
272 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
273 const char *temp_loopback_device, uid_t uid)
278 if (pkgid == NULL || temp_loopback_device == NULL) {
279 _E("invalid argument");
283 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
286 _E("dmcrypt setup device error(%d)", ret);
290 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
293 _E("dmcrypt open device error");
300 int _app2sd_create_loopback_device(const char *pkgid,
301 const char *loopback_device, int size)
304 char command[FILENAME_MAX];
307 const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
308 "bs=1M", buff, NULL };
310 if (pkgid == NULL || size <= 0) {
311 _E("invalid argument");
312 return APP2EXT_ERROR_INVALID_ARGUMENTS;
315 fp = fopen(loopback_device, "r+");
317 _W("encrypted file already exists (%s)", loopback_device);
319 return APP2EXT_ERROR_PKG_EXISTS;
322 snprintf(command, sizeof(command), "of=%s", loopback_device);
323 snprintf(buff, sizeof(buff), "count=%d", size);
325 ret = _xsystem(argv);
327 _E("command (%s) failed, ret(%d), errno(%d)",
328 command, ret, errno);
333 int _app2sd_delete_loopback_device(const char *loopback_device)
337 ret = unlink(loopback_device);
339 if (errno == ENOENT) {
340 _W("unable to access file (%s)", loopback_device);
342 _E("unable to delete (%s)", loopback_device);
343 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
347 return APP2EXT_SUCCESS;
350 int _app2sd_create_file_system(const char *device_path)
356 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
358 if (device_path == NULL) {
360 return APP2EXT_ERROR_INVALID_ARGUMENTS;
363 /* Format the filesystem [create a filesystem]*/
364 fp = fopen(device_path, "r+");
366 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
367 _E("unable to access (%s) error is (%d, %s)",
368 device_path, errno, err_str);
369 return APP2EXT_ERROR_ACCESS_FILE;
373 ret = _xsystem(argv);
375 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
376 _E("creating file system failed, error is (%s)", err_str);
377 return APP2EXT_ERROR_CREATE_FS;
382 static int _app2sd_create_dir_with_link(const char *application_path,
383 const char *pkgid, const char *dir_name, uid_t uid)
386 char app_dir_mmc_path[FILENAME_MAX];
387 char app_dir_path[FILENAME_MAX];
389 snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
390 application_path, dir_name);
391 snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
392 application_path, dir_name);
394 ret = _app2sd_make_directory(app_dir_mmc_path, uid);
396 _E("create directory failed");
397 return APP2EXT_ERROR_CREATE_DIRECTORY;
400 ret = symlink(app_dir_mmc_path, app_dir_path);
402 if (errno == EEXIST) {
403 _D("file with symlink name present (%s)", app_dir_path);
405 _E("symbolic link creation failed, error: %d", errno);
406 return APP2EXT_ERROR_CREATE_SYMLINK;
410 return APP2EXT_SUCCESS;
413 static int _app2sd_create_directory_entry(const char *application_path,
414 const char *pkgid, GList *dir_list, uid_t uid)
418 app2ext_dir_details *dir_detail;
420 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
421 dir_detail = (app2ext_dir_details *)list->data;
422 if (dir_detail == NULL || dir_detail->name == NULL ||
423 dir_detail->type != APP2EXT_DIR_RO)
425 ret = _app2sd_create_dir_with_link(application_path,
426 pkgid, dir_detail->name, uid);
430 return APP2EXT_SUCCESS;
433 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
434 const char *dev, int mount_type, GList *dir_list,
435 app2sd_cmd cmd, uid_t uid)
439 char app_mmc_path[FILENAME_MAX];
440 char temp_path[FILENAME_MAX];
443 struct timespec time = {
445 .tv_nsec = 1000 * 1000 * 200
447 char mountflags_str[BUF_SIZE];
448 const char *argv_mount[] = { "/bin/app2sd-mount-helper", dev,
449 app_mmc_path, FS_TYPE, mountflags_str, NULL };
452 _E("input param is NULL (%s)", dev);
453 return APP2EXT_ERROR_INVALID_ARGUMENTS;
456 /* check directory existence */
457 fd = open(application_path, O_RDONLY | O_DIRECTORY);
459 _E("path(%s) error(%d)", application_path, errno);
460 return APP2EXT_ERROR_OPEN_DIR;
464 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
466 if (ret < 0 || ret > sizeof(app_mmc_path)) {
468 return APP2EXT_ERROR_OPEN_DIR;
470 fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
472 _E("path(%s) error(%d)", app_mmc_path, errno);
473 return APP2EXT_ERROR_OPEN_DIR;
477 nanosleep(&time, NULL); /* 200ms sleep */
478 _D("give a delay for mount");
480 switch (mount_type) {
482 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
483 MS_MGC_VAL | MS_RDONLY | MS_NOSUID);
484 ret = _xsystem(argv_mount);
486 _E("read only mount failed, errono is (%d), "
487 "dev is (%s) path is (%s)",
488 ret, dev, app_mmc_path);
489 ret = APP2EXT_ERROR_MOUNT;
493 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
494 MS_MGC_VAL | MS_NOSUID);
495 ret = _xsystem(argv_mount);
497 _E("read write mount failed, errno is (%d)", ret);
498 ret = APP2EXT_ERROR_MOUNT;
501 case MOUNT_TYPE_RW_NOEXEC:
502 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
503 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID);
504 ret = _xsystem(argv_mount);
506 _E("rwnx mount failed errno is (%d)", ret);
507 ret = APP2EXT_ERROR_MOUNT;
510 case MOUNT_TYPE_RD_REMOUNT:
511 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
512 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT |
514 ret = _xsystem(argv_mount);
516 _E("read remount failed errno is (%d)", ret);
517 ret = APP2EXT_ERROR_MOUNT;
520 case MOUNT_TYPE_RW_REMOUNT:
521 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
522 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID);
523 ret = _xsystem(argv_mount);
524 err_str = strerror_r(ret, err_buf, sizeof(err_buf));
526 _E("read write remount failed errno(%d), errstr(%s)",
528 ret = APP2EXT_ERROR_MOUNT;
532 _E("invalid mount type");
536 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
537 cmd == APP2SD_PRE_UPGRADE) {
538 ret = _app2sd_create_directory_entry(application_path,
539 pkgid, dir_list, uid);
542 if (mount_type != MOUNT_TYPE_RD &&
543 mount_type != MOUNT_TYPE_RD_REMOUNT) {
544 /* change lost+found permission */
545 ret = snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
547 if (ret < 0 || ret > sizeof(temp_path)) {
549 return APP2EXT_ERROR_CREATE_DIRECTORY;
551 ret = _app2sd_make_directory(temp_path, uid);
553 _E("create directory(%s) failed", temp_path);
554 return APP2EXT_ERROR_CREATE_DIRECTORY;
561 int _app2sd_unmount_app_content(const char *application_path)
564 char app_mmc_path[FILENAME_MAX];
568 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
570 ret = umount(app_mmc_path);
572 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
573 _D("unable to umount the dir, ret(%d) error(%d, %s)",
574 ret, errno, err_str);
580 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
586 ret = _app2sd_copy_dir(src_path, arch_path);
587 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
588 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
589 _E("unable to copy from (%s) to (%s), err is (%s)",
590 src_path, arch_path, err_str);
591 return APP2EXT_ERROR_MOVE;
594 ret = _app2sd_delete_directory(src_path);
596 _E("unable to delete (%s)", src_path);
597 return APP2EXT_ERROR_DELETE_DIRECTORY;
603 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
604 uid_t uid, char *mmc_path, char **image_path)
607 mode_t mode = DIR_PERMS;
608 char temp_dir_path[FILENAME_MAX];
609 char app_mmc_path[FILENAME_MAX];
610 char app_archive_path[FILENAME_MAX];
611 char application_path[FILENAME_MAX];
612 char loopback_device[FILENAME_MAX];
613 unsigned long long total_size = 0;
620 app2ext_dir_details *dir_detail;
624 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
625 loopback_device, sizeof(loopback_device));
629 _app2sd_set_application_path(pkgid, uid, application_path,
630 sizeof(application_path));
632 /* check whether application is in external memory or not */
633 fp = fopen(loopback_device, "r+");
635 _W("Already %s entry is present in the SD Card, "
636 "delete entry and go on without return", pkgid);
638 _app2sd_force_clean(pkgid, application_path, loopback_device,
642 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
644 if (ret < 0 || ret > sizeof(app_mmc_path)) {
646 return APP2EXT_ERROR_CREATE_DIRECTORY;
648 ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
650 if (ret < 0 || ret > sizeof(app_archive_path)) {
652 return APP2EXT_ERROR_CREATE_DIRECTORY;
655 ret = mkdir(app_mmc_path, mode);
657 if (errno != EEXIST) {
658 _E("unable to create directory for archiving,"
659 " error(%d)", errno);
660 return APP2EXT_ERROR_CREATE_DIRECTORY;
664 ret = mkdir(app_archive_path, mode);
666 if (errno != EEXIST) {
667 _E("unable to create directory for archiving,"
668 " error(%d)", errno);
669 return APP2EXT_ERROR_CREATE_DIRECTORY;
673 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
674 dir_detail = (app2ext_dir_details *)list->data;
675 if (dir_detail == NULL || dir_detail->name == NULL ||
676 dir_detail->type != APP2EXT_DIR_RO)
678 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
679 application_path, dir_detail->name);
680 if (ret < 0 || ret > sizeof(temp_dir_path)) {
682 return APP2EXT_ERROR_MMC_STATUS;
684 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
685 total_size += _app2sd_calculate_dir_size(temp_dir_path);
688 reqd_size = ((total_size) / (1024 * 1024)) + 2;
689 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
691 /* find avialable free memory in the MMC card */
692 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
694 _E("unable to get available free memory in MMC (%d)", ret);
695 return APP2EXT_ERROR_MMC_STATUS;
697 /* if avaialalbe free memory in MMC is less than
698 * required size + 5MB, return error
700 if (reqd_disk_size > free_mmc_mem) {
701 _E("insufficient memory in MMC for "
702 "application installation (%d)", ret);
703 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
705 /* create a loopback device */
706 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
707 (reqd_disk_size + PKG_BUF_SIZE));
709 _E("loopback node creation failed");
713 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
715 _E("dmcrypt setup device error(%d)", ret);
716 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
719 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
722 _E("dmcrypt open device error");
723 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
725 /* format the loopback file system */
726 ret = _app2sd_create_file_system(device_node);
728 _E("create ext4 filesystem failed");
729 ret = APP2EXT_ERROR_CREATE_FS;
733 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
734 dir_detail = (app2ext_dir_details *)list->data;
735 if (dir_detail == NULL || dir_detail->name == NULL ||
736 dir_detail->type != APP2EXT_DIR_RO)
738 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
739 application_path, dir_detail->name);
740 if (ret < 0 || ret > sizeof(temp_dir_path)) {
742 ret = APP2EXT_ERROR_MOVE;
745 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
746 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
748 _E("unable to copy from (%s) to (%s)",
749 temp_dir_path, app_archive_path);
754 /* mount the loopback encrypted pseudo device on
755 * application installation path as with Read Write permission
757 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
758 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
764 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
765 dir_detail = (app2ext_dir_details *)list->data;
766 if (dir_detail == NULL || dir_detail->name == NULL ||
767 dir_detail->type != APP2EXT_DIR_RO)
769 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
770 app_archive_path, dir_detail->name);
771 if (ret < 0 || ret > sizeof(temp_dir_path)) {
773 ret = APP2EXT_ERROR_COPY_DIRECTORY;
776 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
777 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
779 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
780 _E("unable to access (%s)", temp_dir_path);
782 err_str = strerror_r(errno, err_buf,
784 _E("unable to copy from (%s) to (%s),"
785 " error is (%s)", temp_dir_path,
786 app_mmc_path, err_str);
790 ret = _app2sd_delete_directory(temp_dir_path);
792 _E("unable to delete (%s)", temp_dir_path);
797 ret = _app2sd_delete_directory(app_archive_path);
799 _E("unable to delete (%s)", app_archive_path);
800 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
804 *image_path = strdup(loopback_device);
805 return APP2EXT_SUCCESS;
815 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
816 uid_t uid, char *mmc_path)
819 mode_t mode = DIR_PERMS;
820 char temp_dir_path[FILENAME_MAX];
821 char app_mmc_path[FILENAME_MAX];
822 char app_archive_path[FILENAME_MAX];
823 char application_path[FILENAME_MAX];
824 char loopback_device[FILENAME_MAX];
828 app2ext_dir_details *dir_detail;
830 int free_internal_mem;
831 unsigned long long temp = 0;
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 _E("application (%s) is not installed on SD Card",
849 return APP2EXT_ERROR_FILE_ABSENT;
853 /* find avialable free memory in the internal storage */
854 ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
857 _E("unable to get available free memory in internal (%d)", ret);
858 return APP2EXT_ERROR_MMC_STATUS;
861 fp = fopen(loopback_device, "r+");
863 _E("app entry is not present in SD card");
864 return APP2EXT_ERROR_INVALID_PACKAGE;
868 /* get installed app size*/
869 temp = _app2sd_calculate_file_size(loopback_device);
870 reqd_size = (int)((temp) / (1024 * 1024));
871 _D("reqd size is (%d)", reqd_size);
873 if (reqd_size == 0) {
874 _E("app entry is not present in SD Card");
875 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
878 _I("reqd size: (%d)MB, free internal mem: (%d)MB",
879 reqd_size, free_internal_mem);
881 /* if avaialalbe free memory in internal storage is
882 * less than required size, return error
884 if (reqd_size > free_internal_mem) {
885 _E("innsufficient memory in internal storage"
886 " for application installation (%d)", ret);
887 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
891 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
892 if (device_node == NULL) {
893 /* do loopback setup */
894 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
895 false, uid, &device_node);
897 _E("dmcrypt open device error(%d)", ret);
898 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
900 mount_type = MOUNT_TYPE_RW;
902 mount_type = MOUNT_TYPE_RW_REMOUNT;
905 ret = _app2sd_mount_app_content(application_path,
906 pkgid, device_node, mount_type,
907 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
910 ret = APP2EXT_ERROR_MOUNT_PATH;
914 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
916 if (ret < 0 || ret > sizeof(app_mmc_path)) {
921 ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
923 if (ret < 0 || ret > sizeof(app_archive_path)) {
929 ret = mkdir(app_archive_path, mode);
931 if (errno != EEXIST) {
932 _E("unable to create directory for archiving,"
933 " error(%d)", errno);
934 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
939 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
940 dir_detail = (app2ext_dir_details *)list->data;
941 if (dir_detail == NULL || dir_detail->name == NULL ||
942 dir_detail->type != APP2EXT_DIR_RO)
945 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
946 app_mmc_path, dir_detail->name);
947 if (ret < 0 || ret > sizeof(temp_dir_path)) {
952 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
953 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
955 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
956 _E("unable to access (%s)", temp_dir_path);
958 err_str = strerror_r(errno, err_buf,
960 _E("unable to copy from (%s) to (%s),"
961 "error is (%s)", temp_dir_path,
962 app_archive_path, err_str);
966 /* delete the symbolic link files [bin, lib, res]*/
967 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
968 application_path, dir_detail->name);
969 if (ret < 0 || ret > sizeof(temp_dir_path)) {
974 _D("unlink, temp_dir_path(%s)", temp_dir_path);
975 ret = unlink(temp_dir_path);
977 if (errno == ENOENT) {
978 _W("(%s) does not exist", temp_dir_path);
980 _E("unable to remove the symbolic link file "
981 "(%s), it is already unlinked",
986 /* Copy content to destination */
987 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
988 app_archive_path, dir_detail->name);
989 if (ret < 0 || ret > sizeof(temp_dir_path)) {
994 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
995 ret = _app2sd_copy_dir(temp_dir_path, application_path);
997 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
998 _E("unable to access (%s)", temp_dir_path);
1000 err_str = strerror_r(errno, err_buf,
1002 _E("unable to copy from (%s) to (%s), "
1003 "error is (%s)", temp_dir_path,
1004 application_path, err_str);
1010 _D("copying file completed");
1011 ret = _app2sd_unmount_app_content(application_path);
1013 _E("unable to unmount SD directory for app (%s)", pkgid);
1015 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1017 _E("close dmcrypt device error(%d)", ret);
1019 ret = _app2sd_delete_loopback_device(loopback_device);
1021 _E("unable to delete the loopback device for (%s)", pkgid);
1023 ret = _app2sd_delete_directory(app_mmc_path);
1025 _E("unable to delete (%s)", app_mmc_path);
1027 ret = _app2sd_delete_directory(app_archive_path);
1029 _E("unable to delete (%s)", app_archive_path);
1031 /* remove passwrd from DB */
1032 ret = _app2sd_initialize_db();
1034 _E("app2sd db initialize failed");
1036 ret = _app2sd_remove_info_from_db(pkgid, uid);
1038 _E("cannot remove info from db");
1040 return APP2EXT_SUCCESS;
1049 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1050 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
1054 switch (move_type) {
1055 case APP2EXT_MOVE_TO_EXT:
1056 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1057 uid, mmc_path, image_path);
1059 _E("move app to external memory failed(%d)", ret);
1063 case APP2EXT_MOVE_TO_PHONE:
1064 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1067 _E("move app to internal memory failed(%d)", ret);
1072 _E("invalid argument");
1073 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1079 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1081 char path[FILENAME_MAX];
1084 app2ext_dir_details *dir_detail;
1086 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1087 dir_detail = (app2ext_dir_details *)list->data;
1088 if (dir_detail == NULL || dir_detail->name == NULL ||
1089 dir_detail->type != APP2EXT_DIR_RO)
1092 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1093 ret = _app2sd_copy_dir(path, dest);
1095 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1096 _E("unable to access (%s)", path);
1098 _E("unable to copy from (%s) "
1099 "to (%s), errno is (%d)",
1101 return APP2EXT_ERROR_MOVE;
1106 return APP2EXT_SUCCESS;
1109 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1110 const char *temp_pkgid, const char *temp_application_path,
1111 const char *temp_loopback_device, GList *dir_list,
1112 char *dev_node, int size, uid_t uid)
1117 /* create a new loopback device */
1118 ret = _app2sd_create_loopback_device(temp_pkgid,
1119 temp_loopback_device, (size + PKG_BUF_SIZE));
1121 _E("package already present");
1125 /* perform loopback encryption setup */
1126 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1127 temp_loopback_device, uid);
1129 _E("dmcrypt duplicate encryption setup failed");
1130 _app2sd_delete_loopback_device(temp_loopback_device);
1131 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1134 /* format the loopback file system */
1135 ret = _app2sd_create_file_system(dev_node);
1137 _E("creating fs failed");
1138 err_res = APP2EXT_ERROR_CREATE_FS;
1141 _D("create filesystem SUCCESS");
1143 /* do mounting for new dev*/
1144 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1145 dev_node, MOUNT_TYPE_RW, dir_list,
1146 APP2SD_PRE_UPGRADE, uid);
1148 _E("remount failed");
1149 err_res = APP2EXT_ERROR_MOUNT_PATH;
1153 return APP2EXT_SUCCESS;
1157 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1159 _E("close dmcrypt device error(%d)", ret);
1160 _app2sd_delete_loopback_device(temp_loopback_device);
1167 int _app2sd_update_loopback_device_size(const char *pkgid,
1168 const char *loopback_device, const char *application_path,
1169 const char *temp_pkgid, const char *temp_loopback_device,
1170 const char *temp_application_path, int size, GList *dir_list,
1174 char *old_device_node;
1176 char app_mmc_path[FILENAME_MAX];
1177 char temp_app_mmc_path[FILENAME_MAX];
1180 ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1181 temp_application_path, temp_loopback_device,
1182 dir_list, NULL, size, uid);
1184 _E("creating duplicate device failed");
1188 /* get the associated device node for SD card applicatione */
1190 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1191 if (old_device_node == NULL) {
1192 /* do loopback setup */
1193 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1194 false, uid, &old_device_node);
1196 _E("dmcrypt open device error");
1197 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1200 mount_type = MOUNT_TYPE_RW;
1202 mount_type = MOUNT_TYPE_RW_REMOUNT;
1206 ret = _app2sd_mount_app_content(application_path, pkgid,
1207 old_device_node, mount_type, dir_list,
1208 APP2SD_PRE_UPGRADE, uid);
1210 _E("remount failed");
1211 err_res = APP2EXT_ERROR_MOUNT_PATH;
1213 free(old_device_node);
1215 snprintf(app_mmc_path, sizeof(app_mmc_path),
1216 "%s/.mmc", application_path);
1217 snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1218 "%s/.mmc", temp_application_path);
1220 ret = _app2sd_copy_ro_content(app_mmc_path,
1221 temp_app_mmc_path, dir_list);
1223 _E("copy ro content failed");
1227 ret = _app2sd_unmount_app_content(application_path);
1229 _E("unable to unmount the SD application");
1230 err_res = APP2EXT_ERROR_UNMOUNT;
1233 ret = _app2sd_unmount_app_content(temp_application_path);
1235 _E("unable to unmount the SD application");
1236 err_res = APP2EXT_ERROR_UNMOUNT;
1240 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1242 _E("close dmcrypt device error(%d)", ret);
1243 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1247 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1249 _E("close dmcrypt device error(%d)", ret);
1250 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1254 ret = _app2sd_delete_directory(loopback_device);
1256 _E("unable to delete (%s)", loopback_device);
1257 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1261 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1263 _E("unable to rename (%s)", temp_loopback_device);
1264 err_res = APP2EXT_ERROR_MOVE;
1268 ret = _app2sd_delete_directory(temp_application_path);
1270 _E("unable to delete (%s)", temp_application_path);
1271 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1275 return APP2EXT_SUCCESS;
1278 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1280 _E("close dmcrypt device error(%d)", ret);
1282 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1284 _E("close dmcrypt device error(%d)", ret);
1286 _app2sd_delete_loopback_device(temp_loopback_device);
1288 ret = _app2sd_delete_directory(temp_application_path);
1290 _E("unable to delete (%s)", temp_application_path);
1295 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1296 const char *loopback_device, uid_t uid)
1300 /* unmount the loopback encrypted pseudo device from
1301 * the application installation path
1303 ret = _app2sd_unmount_app_content(application_path);
1305 _W("unable to unmount the app content (%d)", ret);
1307 /* detach the loopback encryption setup for the application */
1308 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1310 _W("close dmcrypt device error (%d)", ret);
1312 /* delete the loopback device from the SD card */
1313 ret = _app2sd_delete_loopback_device(loopback_device);
1315 _W("unable to detach the loopback encryption setup for "
1318 /* delete symlink */
1319 _app2sd_delete_symlink(application_path);
1321 /* remove passwrd from DB */
1322 ret = _app2sd_initialize_db();
1324 _W("app2sd db initialize failed");
1326 ret = _app2sd_remove_info_from_db(pkgid, uid);
1328 _W("cannot remove info from db");