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_crypt.h"
30 #include "app2sd_internals.h"
32 #define DMCRYPT_ITER_TIME 50
33 #define DMCRYPT_KEY_LEN 128
35 static int _app2sd_make_directory(const char *path, uid_t uid)
39 mode_t mode = DIR_PERMS;
41 struct passwd *pwd_result;
44 ret = _app2sd_delete_directory(path);
46 _E("unable to delete (%s), errno(%d)", path, errno);
47 return APP2EXT_ERROR_DELETE_DIRECTORY;
50 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
51 if (ret != 0 || pwd_result == NULL) {
52 _E("get uid failed(%d)", ret);
53 return APP2EXT_ERROR_ACCESS_FILE;
55 _D("uid(%d), gid(%d)", uid, pwd.pw_gid);
57 /* create directory */
58 ret = mkdir(path, mode);
60 if (errno != EEXIST) {
61 _E("create directory failed, error is (%d)", errno);
62 return APP2EXT_ERROR_CREATE_DIRECTORY;
66 fd = open(path, O_RDONLY|O_DIRECTORY);
68 _E("can't open path(%s)", path);
69 return APP2EXT_ERROR_OPEN_DIR;
72 ret = fchmod(fd, 0755);
74 _E("change file permission error");
76 return APP2EXT_ERROR_ACCESS_FILE;
79 ret = fchown(fd, uid, pwd.pw_gid);
81 _E("change file owner error");
83 return APP2EXT_ERROR_ACCESS_FILE;
88 return APP2EXT_SUCCESS;
91 int _app2sd_dmcrypt_setup_device(const char *pkgid,
92 const char *loopback_device, bool is_dup, uid_t uid)
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 ret = _app2sd_crypt_luks_format(loopback_device, passwd);
133 memset(passwd, 0, strlen(passwd));
136 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
137 _E("Error setting up dmcrypt on app2sd file, error:%s, ret:%d",
139 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
145 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
146 bool is_dup, uid_t uid, char **dev_node)
150 char dev_name[BUF_SIZE];
153 if (pkgid == NULL || loopback_device == NULL) {
154 _E("invalid argument");
155 return APP2EXT_ERROR_INVALID_ARGUMENTS;
159 snprintf(dev_name, sizeof(dev_name), "%s.new_%d", pkgid, uid);
161 snprintf(dev_name, sizeof(dev_name), "%s_%d", pkgid, uid);
163 /* get password for dmcrypt encryption */
164 ret = _app2sd_initialize_db();
166 _E("app2sd db initialize failed");
167 return APP2EXT_ERROR_DB_INITIALIZE;
170 passwd = _app2sd_get_password_from_db(pkgid, uid);
171 if (passwd == NULL) {
172 _E("no password found for [%s]", pkgid);
173 return APP2EXT_ERROR_SQLITE_REGISTRY;
176 if (_app2sd_crypt_is_luks(loopback_device) == 0) {
177 _W("legacy image format!");
178 ret = _app2sd_crypt_plain_open(loopback_device, passwd,
181 ret = _app2sd_crypt_luks_open(loopback_device, passwd,
186 _E("error opening dmcrypt device");
187 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
190 snprintf(buf, sizeof(buf), "/dev/mapper/%s", dev_name);
191 *dev_node = strdup(buf);
192 if (*dev_node == NULL) {
193 _E("memory alloc failed");
194 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
200 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
203 char dev_node[BUF_SIZE];
207 _E("invalid argument");
208 return APP2EXT_ERROR_INVALID_ARGUMENTS;
211 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
213 _W("no associated device node(%s_%d) found", pkgid, uid);
214 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
219 snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
220 ret = _app2sd_crypt_luks_close(dev_node);
222 _E("error closing dmcrypt on app2sd file: %s", dev_node);
223 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
229 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
234 snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
235 if (access(buf, F_OK) == 0) {
236 dev_node = strdup(buf);
237 if (dev_node == NULL) {
238 _E("memory alloc failed");
241 _D("device_node: (%s)", dev_node);
244 _D("can not access dev_node(%s), errno(%d)", buf, errno);
249 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
250 const char *temp_loopback_device, uid_t uid)
255 if (pkgid == NULL || temp_loopback_device == NULL) {
256 _E("invalid argument");
260 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
263 _E("dmcrypt setup device error(%d)", ret);
267 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
270 _E("dmcrypt open device error");
277 int _app2sd_create_loopback_device(const char *pkgid,
278 const char *loopback_device, int size)
281 char command[FILENAME_MAX];
284 const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
285 "bs=1M", buff, NULL };
287 if (pkgid == NULL || size <= 0) {
288 _E("invalid argument");
289 return APP2EXT_ERROR_INVALID_ARGUMENTS;
292 fp = fopen(loopback_device, "r+");
294 _W("encrypted file already exists (%s)", loopback_device);
296 return APP2EXT_ERROR_PKG_EXISTS;
299 snprintf(command, sizeof(command), "of=%s", loopback_device);
300 snprintf(buff, sizeof(buff), "count=%d", size);
302 ret = _xsystem(argv);
304 _E("command (%s) failed, ret(%d), errno(%d)",
305 command, ret, errno);
310 int _app2sd_delete_loopback_device(const char *loopback_device)
314 ret = unlink(loopback_device);
316 if (errno == ENOENT) {
317 _W("unable to access file (%s)", loopback_device);
319 _E("unable to delete (%s)", loopback_device);
320 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
324 return APP2EXT_SUCCESS;
327 int _app2sd_create_file_system(const char *device_path)
333 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
335 if (device_path == NULL) {
337 return APP2EXT_ERROR_INVALID_ARGUMENTS;
340 /* Format the filesystem [create a filesystem]*/
341 fp = fopen(device_path, "r+");
343 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
344 _E("unable to access (%s) error is (%d, %s)",
345 device_path, errno, err_buf);
346 return APP2EXT_ERROR_ACCESS_FILE;
350 ret = _xsystem(argv);
352 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
353 _E("creating file system failed, error is (%s)", err_str);
354 return APP2EXT_ERROR_CREATE_FS;
359 static int _app2sd_create_dir_with_link(const char *application_path,
360 const char *pkgid, const char *dir_name, uid_t uid)
363 char app_dir_mmc_path[FILENAME_MAX];
364 char app_dir_path[FILENAME_MAX];
366 snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
367 application_path, dir_name);
368 snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
369 application_path, dir_name);
371 ret = _app2sd_make_directory(app_dir_mmc_path, uid);
373 _E("create directory failed");
374 return APP2EXT_ERROR_CREATE_DIRECTORY;
377 ret = symlink(app_dir_mmc_path, app_dir_path);
379 if (errno == EEXIST) {
380 _D("file with symlink name present (%s)", app_dir_path);
382 _E("symbolic link creation failed, error: %d", errno);
383 return APP2EXT_ERROR_CREATE_SYMLINK;
387 return APP2EXT_SUCCESS;
390 static int _app2sd_create_directory_entry(const char *application_path,
391 const char *pkgid, GList *dir_list, uid_t uid)
395 app2ext_dir_details *dir_detail;
397 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
398 dir_detail = (app2ext_dir_details *)list->data;
399 if (dir_detail == NULL || dir_detail->name == NULL ||
400 dir_detail->type != APP2EXT_DIR_RO)
402 ret = _app2sd_create_dir_with_link(application_path,
403 pkgid, dir_detail->name, uid);
407 return APP2EXT_SUCCESS;
410 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
411 const char *dev, int mount_type, GList *dir_list,
412 app2sd_cmd cmd, uid_t uid)
416 char app_mmc_path[FILENAME_MAX];
417 char temp_path[FILENAME_MAX];
420 struct timespec time = {
422 .tv_nsec = 1000 * 1000 * 200
424 char mountflags_str[BUF_SIZE];
425 const char *argv_mount[] = { "/bin/app2sd-mount-helper", dev,
426 app_mmc_path, FS_TYPE, mountflags_str, NULL };
429 _E("input param is NULL (%s)", dev);
430 return APP2EXT_ERROR_INVALID_ARGUMENTS;
433 /* check directory existence */
434 fd = open(application_path, O_RDONLY | O_DIRECTORY);
436 _E("path(%s) error(%d)", application_path, errno);
437 return APP2EXT_ERROR_OPEN_DIR;
441 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
443 fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
445 _E("path(%s) error(%d)", app_mmc_path, errno);
446 return APP2EXT_ERROR_OPEN_DIR;
450 nanosleep(&time, NULL); /* 200ms sleep */
451 _D("give a delay for mount");
453 switch (mount_type) {
455 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
456 MS_MGC_VAL | MS_RDONLY | MS_NOSUID);
457 ret = _xsystem(argv_mount);
459 _E("read only mount failed, errono is (%d), "
460 "dev is (%s) path is (%s)",
461 ret, dev, app_mmc_path);
462 ret = APP2EXT_ERROR_MOUNT;
466 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
467 MS_MGC_VAL | MS_NOSUID);
468 ret = _xsystem(argv_mount);
470 _E("read write mount failed, errno is (%d)", ret);
471 ret = APP2EXT_ERROR_MOUNT;
474 case MOUNT_TYPE_RW_NOEXEC:
475 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
476 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID);
477 ret = _xsystem(argv_mount);
479 _E("rwnx mount failed errno is (%d)", ret);
480 ret = APP2EXT_ERROR_MOUNT;
483 case MOUNT_TYPE_RD_REMOUNT:
484 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
485 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT |
487 ret = _xsystem(argv_mount);
489 _E("read remount failed errno is (%d)", ret);
490 ret = APP2EXT_ERROR_MOUNT;
493 case MOUNT_TYPE_RW_REMOUNT:
494 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
495 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID);
496 ret = _xsystem(argv_mount);
497 err_str = strerror_r(ret, err_buf, sizeof(err_buf));
499 _E("read write remount failed errno(%d), errstr(%s)",
501 ret = APP2EXT_ERROR_MOUNT;
505 _E("invalid mount type");
509 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
510 cmd == APP2SD_PRE_UPGRADE) {
511 ret = _app2sd_create_directory_entry(application_path,
512 pkgid, dir_list, uid);
515 if (mount_type != MOUNT_TYPE_RD &&
516 mount_type != MOUNT_TYPE_RD_REMOUNT) {
517 /* change lost+found permission */
518 snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
520 ret = _app2sd_make_directory(temp_path, uid);
522 _E("create directory(%s) failed", temp_path);
523 return APP2EXT_ERROR_CREATE_DIRECTORY;
530 int _app2sd_unmount_app_content(const char *application_path)
533 char app_mmc_path[FILENAME_MAX];
537 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
539 ret = umount(app_mmc_path);
541 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
542 _D("unable to umount the dir, ret(%d) error(%d, %s)",
543 ret, errno, err_str);
549 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
555 ret = _app2sd_copy_dir(src_path, arch_path);
556 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
557 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
558 _E("unable to copy from (%s) to (%s), err is (%s)",
559 src_path, arch_path, err_str);
560 return APP2EXT_ERROR_MOVE;
563 ret = _app2sd_delete_directory(src_path);
565 _E("unable to delete (%s)", src_path);
566 return APP2EXT_ERROR_DELETE_DIRECTORY;
572 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
573 uid_t uid, char *mmc_path, char **image_path)
576 mode_t mode = DIR_PERMS;
577 char temp_dir_path[FILENAME_MAX];
578 char app_mmc_path[FILENAME_MAX];
579 char app_archive_path[FILENAME_MAX];
580 char application_path[FILENAME_MAX];
581 char loopback_device[FILENAME_MAX];
582 unsigned long long total_size = 0;
589 app2ext_dir_details *dir_detail;
593 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
594 loopback_device, sizeof(loopback_device));
598 _app2sd_set_application_path(pkgid, uid, application_path,
599 sizeof(application_path));
601 /* check whether application is in external memory or not */
602 fp = fopen(loopback_device, "r+");
604 _W("Already %s entry is present in the SD Card, "
605 "delete entry and go on without return", pkgid);
607 _app2sd_force_clean(pkgid, application_path, loopback_device,
611 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
613 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
616 ret = mkdir(app_mmc_path, mode);
618 if (errno != EEXIST) {
619 _E("unable to create directory for archiving,"
620 " error(%d)", errno);
621 return APP2EXT_ERROR_CREATE_DIRECTORY;
625 ret = mkdir(app_archive_path, mode);
627 if (errno != EEXIST) {
628 _E("unable to create directory for archiving,"
629 " error(%d)", errno);
630 return APP2EXT_ERROR_CREATE_DIRECTORY;
634 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
635 dir_detail = (app2ext_dir_details *)list->data;
636 if (dir_detail == NULL || dir_detail->name == NULL ||
637 dir_detail->type != APP2EXT_DIR_RO)
639 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
640 application_path, dir_detail->name);
641 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
642 total_size += _app2sd_calculate_dir_size(temp_dir_path);
645 reqd_size = ((total_size) / (1024 * 1024)) + 2;
646 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
648 /* find avialable free memory in the MMC card */
649 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
651 _E("unable to get available free memory in MMC (%d)", ret);
652 return APP2EXT_ERROR_MMC_STATUS;
654 /* if avaialalbe free memory in MMC is less than
655 * required size + 5MB, return error
657 if (reqd_disk_size > free_mmc_mem) {
658 _E("insufficient memory in MMC for "
659 "application installation (%d)", ret);
660 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
662 /* create a loopback device */
663 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
664 (reqd_disk_size + PKG_BUF_SIZE));
666 _E("loopback node creation failed");
670 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
672 _E("dmcrypt setup device error(%d)", ret);
673 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
676 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
679 _E("dmcrypt open device error");
680 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
682 /* format the loopback file system */
683 ret = _app2sd_create_file_system(device_node);
685 _E("create ext4 filesystem failed");
686 ret = APP2EXT_ERROR_CREATE_FS;
690 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
691 dir_detail = (app2ext_dir_details *)list->data;
692 if (dir_detail == NULL || dir_detail->name == NULL ||
693 dir_detail->type != APP2EXT_DIR_RO)
695 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
696 application_path, dir_detail->name);
697 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
698 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
700 _E("unable to copy from (%s) to (%s)",
701 temp_dir_path, app_archive_path);
706 /* mount the loopback encrypted pseudo device on
707 * application installation path as with Read Write permission
709 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
710 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
716 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
717 dir_detail = (app2ext_dir_details *)list->data;
718 if (dir_detail == NULL || dir_detail->name == NULL ||
719 dir_detail->type != APP2EXT_DIR_RO)
721 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
722 app_archive_path, dir_detail->name);
723 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
724 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
726 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
727 _E("unable to access (%s)", temp_dir_path);
729 err_str = strerror_r(errno, err_buf,
731 _E("unable to copy from (%s) to (%s),"
732 " error is (%s)", temp_dir_path,
733 app_mmc_path, err_str);
737 ret = _app2sd_delete_directory(temp_dir_path);
739 _E("unable to delete (%s)", temp_dir_path);
744 ret = _app2sd_delete_directory(app_archive_path);
746 _E("unable to delete (%s)", app_archive_path);
747 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
751 *image_path = strdup(loopback_device);
752 return APP2EXT_SUCCESS;
762 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
763 uid_t uid, char *mmc_path)
766 mode_t mode = DIR_PERMS;
767 char temp_dir_path[FILENAME_MAX];
768 char app_mmc_path[FILENAME_MAX];
769 char app_archive_path[FILENAME_MAX];
770 char application_path[FILENAME_MAX];
771 char loopback_device[FILENAME_MAX];
775 app2ext_dir_details *dir_detail;
777 int free_internal_mem;
778 unsigned long long temp = 0;
783 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
784 loopback_device, sizeof(loopback_device));
788 _app2sd_set_application_path(pkgid, uid, application_path,
789 sizeof(application_path));
791 /* check whether application is in external memory or not */
792 fp = fopen(loopback_device, "r+");
794 _E("application (%s) is not installed on SD Card",
796 return APP2EXT_ERROR_FILE_ABSENT;
800 /* find avialable free memory in the internal storage */
801 ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
804 _E("unable to get available free memory in internal (%d)", ret);
805 return APP2EXT_ERROR_MMC_STATUS;
808 fp = fopen(loopback_device, "r+");
810 _E("app entry is not present in SD card");
811 return APP2EXT_ERROR_INVALID_PACKAGE;
815 /* get installed app size*/
816 temp = _app2sd_calculate_file_size(loopback_device);
817 reqd_size = (int)((temp) / (1024 * 1024));
818 _D("reqd size is (%d)", reqd_size);
820 if (reqd_size == 0) {
821 _E("app entry is not present in SD Card");
822 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
825 _I("reqd size: (%d)MB, free internal mem: (%d)MB",
826 reqd_size, free_internal_mem);
828 /* if avaialalbe free memory in internal storage is
829 * less than required size, return error
831 if (reqd_size > free_internal_mem) {
832 _E("innsufficient memory in internal storage"
833 " for application installation (%d)", ret);
834 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
838 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
839 if (device_node == NULL) {
840 /* do loopback setup */
841 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
842 false, uid, &device_node);
844 _E("dmcrypt open device error(%d)", ret);
845 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
847 mount_type = MOUNT_TYPE_RW;
849 mount_type = MOUNT_TYPE_RW_REMOUNT;
852 ret = _app2sd_mount_app_content(application_path,
853 pkgid, device_node, mount_type,
854 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
857 ret = APP2EXT_ERROR_MOUNT_PATH;
861 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
863 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
866 ret = mkdir(app_archive_path, mode);
868 if (errno != EEXIST) {
869 _E("unable to create directory for archiving,"
870 " error(%d)", errno);
871 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
876 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
877 dir_detail = (app2ext_dir_details *)list->data;
878 if (dir_detail == NULL || dir_detail->name == NULL ||
879 dir_detail->type != APP2EXT_DIR_RO)
882 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
883 app_mmc_path, dir_detail->name);
884 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
885 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
887 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
888 _E("unable to access (%s)", temp_dir_path);
890 err_str = strerror_r(errno, err_buf,
892 _E("unable to copy from (%s) to (%s),"
893 "error is (%s)", temp_dir_path,
894 app_archive_path, err_str);
898 /* delete the symbolic link files [bin, lib, res]*/
899 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
900 application_path, dir_detail->name);
901 _D("unlink, temp_dir_path(%s)", temp_dir_path);
902 ret = unlink(temp_dir_path);
904 if (errno == ENOENT) {
905 _W("(%s) does not exist", temp_dir_path);
907 _E("unable to remove the symbolic link file "
908 "(%s), it is already unlinked",
913 /* Copy content to destination */
914 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
915 app_archive_path, dir_detail->name);
916 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
917 ret = _app2sd_copy_dir(temp_dir_path, application_path);
919 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
920 _E("unable to access (%s)", temp_dir_path);
922 err_str = strerror_r(errno, err_buf,
924 _E("unable to copy from (%s) to (%s), "
925 "error is (%s)", temp_dir_path,
926 application_path, err_str);
932 _D("copying file completed");
933 ret = _app2sd_unmount_app_content(application_path);
935 _E("unable to unmount SD directory for app (%s)", pkgid);
937 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
939 _E("close dmcrypt device error(%d)", ret);
941 ret = _app2sd_delete_loopback_device(loopback_device);
943 _E("unable to delete the loopback device for (%s)", pkgid);
945 ret = _app2sd_delete_directory(app_mmc_path);
947 _E("unable to delete (%s)", app_mmc_path);
949 ret = _app2sd_delete_directory(app_archive_path);
951 _E("unable to delete (%s)", app_archive_path);
953 /* remove passwrd from DB */
954 ret = _app2sd_initialize_db();
956 _E("app2sd db initialize failed");
958 ret = _app2sd_remove_info_from_db(pkgid, uid);
960 _E("cannot remove info from db");
962 return APP2EXT_SUCCESS;
971 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
972 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
977 case APP2EXT_MOVE_TO_EXT:
978 ret = _app2sd_move_app_to_external(pkgid, dir_list,
979 uid, mmc_path, image_path);
981 _E("move app to external memory failed(%d)", ret);
985 case APP2EXT_MOVE_TO_PHONE:
986 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
989 _E("move app to internal memory failed(%d)", ret);
994 _E("invalid argument");
995 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1001 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1003 char path[FILENAME_MAX];
1006 app2ext_dir_details *dir_detail;
1008 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1009 dir_detail = (app2ext_dir_details *)list->data;
1010 if (dir_detail == NULL || dir_detail->name == NULL ||
1011 dir_detail->type != APP2EXT_DIR_RO)
1014 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1015 ret = _app2sd_copy_dir(path, dest);
1017 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1018 _E("unable to access (%s)", path);
1020 _E("unable to copy from (%s) "
1021 "to (%s), errno is (%d)",
1023 return APP2EXT_ERROR_MOVE;
1028 return APP2EXT_SUCCESS;
1031 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1032 const char *temp_pkgid, const char *temp_application_path,
1033 const char *temp_loopback_device, GList *dir_list,
1034 char *dev_node, int size, uid_t uid)
1039 /* create a new loopback device */
1040 ret = _app2sd_create_loopback_device(temp_pkgid,
1041 temp_loopback_device, (size + PKG_BUF_SIZE));
1043 _E("package already present");
1047 /* perform loopback encryption setup */
1048 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1049 temp_loopback_device, uid);
1051 _E("dmcrypt duplicate encryption setup failed");
1052 _app2sd_delete_loopback_device(temp_loopback_device);
1053 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1056 /* format the loopback file system */
1057 ret = _app2sd_create_file_system(dev_node);
1059 _E("creating fs failed");
1060 err_res = APP2EXT_ERROR_CREATE_FS;
1063 _D("create filesystem SUCCESS");
1065 /* do mounting for new dev*/
1066 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1067 dev_node, MOUNT_TYPE_RW, dir_list,
1068 APP2SD_PRE_UPGRADE, uid);
1070 _E("remount failed");
1071 err_res = APP2EXT_ERROR_MOUNT_PATH;
1075 return APP2EXT_SUCCESS;
1079 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1081 _E("close dmcrypt device error(%d)", ret);
1082 _app2sd_delete_loopback_device(temp_loopback_device);
1089 int _app2sd_update_loopback_device_size(const char *pkgid,
1090 const char *loopback_device, const char *application_path,
1091 const char *temp_pkgid, const char *temp_loopback_device,
1092 const char *temp_application_path, int size, GList *dir_list,
1096 char *old_device_node;
1098 char app_mmc_path[FILENAME_MAX];
1099 char temp_app_mmc_path[FILENAME_MAX];
1102 ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1103 temp_application_path, temp_loopback_device,
1104 dir_list, NULL, size, uid);
1106 _E("creating duplicate device failed");
1110 /* get the associated device node for SD card applicatione */
1112 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1113 if (old_device_node == NULL) {
1114 /* do loopback setup */
1115 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1116 false, uid, &old_device_node);
1118 _E("dmcrypt open device error");
1119 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1122 mount_type = MOUNT_TYPE_RW;
1124 mount_type = MOUNT_TYPE_RW_REMOUNT;
1128 ret = _app2sd_mount_app_content(application_path, pkgid,
1129 old_device_node, mount_type, dir_list,
1130 APP2SD_PRE_UPGRADE, uid);
1132 _E("remount failed");
1133 err_res = APP2EXT_ERROR_MOUNT_PATH;
1135 free(old_device_node);
1137 snprintf(app_mmc_path, sizeof(app_mmc_path),
1138 "%s/.mmc", application_path);
1139 snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1140 "%s/.mmc", temp_application_path);
1142 ret = _app2sd_copy_ro_content(app_mmc_path,
1143 temp_app_mmc_path, dir_list);
1145 _E("copy ro content failed");
1149 ret = _app2sd_unmount_app_content(application_path);
1151 _E("unable to unmount the SD application");
1152 err_res = APP2EXT_ERROR_UNMOUNT;
1155 ret = _app2sd_unmount_app_content(temp_application_path);
1157 _E("unable to unmount the SD application");
1158 err_res = APP2EXT_ERROR_UNMOUNT;
1162 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1164 _E("close dmcrypt device error(%d)", ret);
1165 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1169 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1171 _E("close dmcrypt device error(%d)", ret);
1172 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1176 ret = _app2sd_delete_directory(loopback_device);
1178 _E("unable to delete (%s)", loopback_device);
1179 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1183 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1185 _E("unable to rename (%s)", temp_loopback_device);
1186 err_res = APP2EXT_ERROR_MOVE;
1190 ret = _app2sd_delete_directory(temp_application_path);
1192 _E("unable to delete (%s)", temp_application_path);
1193 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1197 return APP2EXT_SUCCESS;
1200 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1202 _E("close dmcrypt device error(%d)", ret);
1204 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1206 _E("close dmcrypt device error(%d)", ret);
1208 _app2sd_delete_loopback_device(temp_loopback_device);
1210 ret = _app2sd_delete_directory(temp_application_path);
1212 _E("unable to delete (%s)", temp_application_path);
1217 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1218 const char *loopback_device, uid_t uid)
1222 /* unmount the loopback encrypted pseudo device from
1223 * the application installation path
1225 ret = _app2sd_unmount_app_content(application_path);
1227 _W("unable to unmount the app content (%d)", ret);
1229 /* detach the loopback encryption setup for the application */
1230 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1232 _W("close dmcrypt device error (%d)", ret);
1234 /* delete the loopback device from the SD card */
1235 ret = _app2sd_delete_loopback_device(loopback_device);
1237 _W("unable to detach the loopback encryption setup for "
1240 /* delete symlink */
1241 _app2sd_delete_symlink(application_path);
1243 /* remove passwrd from DB */
1244 ret = _app2sd_initialize_db();
1246 _W("app2sd db initialize failed");
1248 ret = _app2sd_remove_info_from_db(pkgid, uid);
1250 _W("cannot remove info from db");