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)) {
192 _E("snprintf fail\n");
196 ret = snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
197 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen "
199 passwd, loopback_device, dev_name);
200 if (ret < 0 || ret > sizeof(dmcrypt_open_cmd)) {
201 _E("snprintf fail\n");
207 ret = system(dmcrypt_open_cmd);
209 err_str = strerror_r(errno, buf, sizeof(buf));
210 _E("error opening dmcrypt device, error: [%s]", err_str);
211 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
214 size = strlen("/dev/mapper/%s") + strlen(dev_name) + 1;
215 *dev_node = (char *)malloc(size);
216 if (*dev_node == NULL) {
217 _E("memory alloc failed");
218 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
220 ret = snprintf(*dev_node, size, "/dev/mapper/%s", dev_name);
221 if (ret < 0 || ret > size) {
222 _E("snprintf fail\n");
228 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
231 char dev_node[BUF_SIZE];
232 char dmcrypt_close_cmd[BUF_SIZE];
233 char err_buf[BUF_SIZE];
238 _E("invalid argument");
239 return APP2EXT_ERROR_INVALID_ARGUMENTS;
242 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
244 _W("no associated device node(%s_%d) found", pkgid, uid);
245 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
250 ret = snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
251 if (ret < 0 || ret > sizeof(dev_node)) {
253 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
255 ret = snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
256 "/sbin/cryptsetup -q luksClose %s", dev_node);
257 if (ret < 0 || ret > sizeof(dmcrypt_close_cmd)) {
259 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
261 ret = system(dmcrypt_close_cmd);
263 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
264 _E("error closing dmcrypt on app2sd file: %s", err_str);
265 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
271 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
276 snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
277 if (access(buf, F_OK) == 0) {
278 dev_node = strdup(buf);
279 if (dev_node == NULL) {
280 _E("memory alloc failed");
283 _D("device_node: (%s)", dev_node);
286 _D("can not access dev_node(%s), errno(%d)", buf, errno);
291 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
292 const char *temp_loopback_device, uid_t uid)
297 if (pkgid == NULL || temp_loopback_device == NULL) {
298 _E("invalid argument");
302 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
305 _E("dmcrypt setup device error(%d)", ret);
309 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
312 _E("dmcrypt open device error");
319 int _app2sd_create_loopback_device(const char *pkgid,
320 const char *loopback_device, int size)
323 char command[FILENAME_MAX];
326 const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
327 "bs=1M", buff, NULL };
329 if (pkgid == NULL || size <= 0) {
330 _E("invalid argument");
331 return APP2EXT_ERROR_INVALID_ARGUMENTS;
334 fp = fopen(loopback_device, "r+");
336 _W("encrypted file already exists (%s)", loopback_device);
338 return APP2EXT_ERROR_PKG_EXISTS;
341 snprintf(command, sizeof(command), "of=%s", loopback_device);
342 snprintf(buff, sizeof(buff), "count=%d", size);
344 ret = _xsystem(argv);
346 _E("command (%s) failed, ret(%d), errno(%d)",
347 command, ret, errno);
352 int _app2sd_delete_loopback_device(const char *loopback_device)
356 ret = unlink(loopback_device);
358 if (errno == ENOENT) {
359 _W("unable to access file (%s)", loopback_device);
361 _E("unable to delete (%s)", loopback_device);
362 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
366 return APP2EXT_SUCCESS;
369 int _app2sd_create_file_system(const char *device_path)
375 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
377 if (device_path == NULL) {
379 return APP2EXT_ERROR_INVALID_ARGUMENTS;
382 /* Format the filesystem [create a filesystem]*/
383 fp = fopen(device_path, "r+");
385 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
386 _E("unable to access (%s) error is (%d, %s)",
387 device_path, errno, err_str);
388 return APP2EXT_ERROR_ACCESS_FILE;
392 ret = _xsystem(argv);
394 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
395 _E("creating file system failed, error is (%s)", err_str);
396 return APP2EXT_ERROR_CREATE_FS;
401 static int _app2sd_create_dir_with_link(const char *application_path,
402 const char *pkgid, const char *dir_name, uid_t uid)
405 char app_dir_mmc_path[FILENAME_MAX];
406 char app_dir_path[FILENAME_MAX];
408 snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
409 application_path, dir_name);
410 snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
411 application_path, dir_name);
413 ret = _app2sd_make_directory(app_dir_mmc_path, uid);
415 _E("create directory failed");
416 return APP2EXT_ERROR_CREATE_DIRECTORY;
419 ret = symlink(app_dir_mmc_path, app_dir_path);
421 if (errno == EEXIST) {
422 _D("file with symlink name present (%s)", app_dir_path);
424 _E("symbolic link creation failed, error: %d", errno);
425 return APP2EXT_ERROR_CREATE_SYMLINK;
429 return APP2EXT_SUCCESS;
432 static int _app2sd_create_directory_entry(const char *application_path,
433 const char *pkgid, GList *dir_list, uid_t uid)
437 app2ext_dir_details *dir_detail;
439 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
440 dir_detail = (app2ext_dir_details *)list->data;
441 if (dir_detail == NULL || dir_detail->name == NULL ||
442 dir_detail->type != APP2EXT_DIR_RO)
444 ret = _app2sd_create_dir_with_link(application_path,
445 pkgid, dir_detail->name, uid);
449 return APP2EXT_SUCCESS;
452 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
453 const char *dev, int mount_type, GList *dir_list,
454 app2sd_cmd cmd, uid_t uid)
458 char app_mmc_path[FILENAME_MAX];
459 char temp_path[FILENAME_MAX];
462 struct timespec time = {
464 .tv_nsec = 1000 * 1000 * 200
466 char mountflags_str[BUF_SIZE];
467 const char *argv_mount[] = { "/bin/app2sd-mount-helper", dev,
468 app_mmc_path, FS_TYPE, mountflags_str, NULL };
471 _E("input param is NULL (%s)", dev);
472 return APP2EXT_ERROR_INVALID_ARGUMENTS;
475 /* check directory existence */
476 fd = open(application_path, O_RDONLY | O_DIRECTORY);
478 _E("path(%s) error(%d)", application_path, errno);
479 return APP2EXT_ERROR_OPEN_DIR;
483 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
485 if (ret < 0 || ret > sizeof(app_mmc_path)) {
487 return APP2EXT_ERROR_OPEN_DIR;
489 fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
491 _E("path(%s) error(%d)", app_mmc_path, errno);
492 return APP2EXT_ERROR_OPEN_DIR;
496 nanosleep(&time, NULL); /* 200ms sleep */
497 _D("give a delay for mount");
499 switch (mount_type) {
501 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
502 MS_MGC_VAL | MS_RDONLY | MS_NOSUID);
503 ret = _xsystem(argv_mount);
505 _E("read only mount failed, errono is (%d), "
506 "dev is (%s) path is (%s)",
507 ret, dev, app_mmc_path);
508 ret = APP2EXT_ERROR_MOUNT;
512 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
513 MS_MGC_VAL | MS_NOSUID);
514 ret = _xsystem(argv_mount);
516 _E("read write mount failed, errno is (%d)", ret);
517 ret = APP2EXT_ERROR_MOUNT;
520 case MOUNT_TYPE_RW_NOEXEC:
521 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
522 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID);
523 ret = _xsystem(argv_mount);
525 _E("rwnx mount failed errno is (%d)", ret);
526 ret = APP2EXT_ERROR_MOUNT;
529 case MOUNT_TYPE_RD_REMOUNT:
530 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
531 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT |
533 ret = _xsystem(argv_mount);
535 _E("read remount failed errno is (%d)", ret);
536 ret = APP2EXT_ERROR_MOUNT;
539 case MOUNT_TYPE_RW_REMOUNT:
540 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
541 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID);
542 ret = _xsystem(argv_mount);
543 err_str = strerror_r(ret, err_buf, sizeof(err_buf));
545 _E("read write remount failed errno(%d), errstr(%s)",
547 ret = APP2EXT_ERROR_MOUNT;
551 _E("invalid mount type");
555 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
556 cmd == APP2SD_PRE_UPGRADE) {
557 ret = _app2sd_create_directory_entry(application_path,
558 pkgid, dir_list, uid);
561 if (mount_type != MOUNT_TYPE_RD &&
562 mount_type != MOUNT_TYPE_RD_REMOUNT) {
563 /* change lost+found permission */
564 ret = snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
566 if (ret < 0 || ret > sizeof(temp_path)) {
568 return APP2EXT_ERROR_CREATE_DIRECTORY;
570 ret = _app2sd_make_directory(temp_path, uid);
572 _E("create directory(%s) failed", temp_path);
573 return APP2EXT_ERROR_CREATE_DIRECTORY;
580 int _app2sd_unmount_app_content(const char *application_path)
583 char app_mmc_path[FILENAME_MAX];
587 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
589 ret = umount(app_mmc_path);
591 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
592 _D("unable to umount the dir, ret(%d) error(%d, %s)",
593 ret, errno, err_str);
599 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
605 ret = _app2sd_copy_dir(src_path, arch_path);
606 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
607 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
608 _E("unable to copy from (%s) to (%s), err is (%s)",
609 src_path, arch_path, err_str);
610 return APP2EXT_ERROR_MOVE;
613 ret = _app2sd_delete_directory(src_path);
615 _E("unable to delete (%s)", src_path);
616 return APP2EXT_ERROR_DELETE_DIRECTORY;
622 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
623 uid_t uid, char *mmc_path, char **image_path)
626 mode_t mode = DIR_PERMS;
627 char temp_dir_path[FILENAME_MAX];
628 char app_mmc_path[FILENAME_MAX];
629 char app_archive_path[FILENAME_MAX];
630 char application_path[FILENAME_MAX];
631 char loopback_device[FILENAME_MAX];
632 unsigned long long total_size = 0;
639 app2ext_dir_details *dir_detail;
643 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
644 loopback_device, sizeof(loopback_device));
648 _app2sd_set_application_path(pkgid, uid, application_path,
649 sizeof(application_path));
651 /* check whether application is in external memory or not */
652 fp = fopen(loopback_device, "r+");
654 _W("Already %s entry is present in the SD Card, "
655 "delete entry and go on without return", pkgid);
657 _app2sd_force_clean(pkgid, application_path, loopback_device,
661 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
663 if (ret < 0 || ret > sizeof(app_mmc_path)) {
665 return APP2EXT_ERROR_CREATE_DIRECTORY;
667 ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
669 if (ret < 0 || ret > sizeof(app_archive_path)) {
671 return APP2EXT_ERROR_CREATE_DIRECTORY;
674 ret = mkdir(app_mmc_path, mode);
676 if (errno != EEXIST) {
677 _E("unable to create directory for archiving,"
678 " error(%d)", errno);
679 return APP2EXT_ERROR_CREATE_DIRECTORY;
683 ret = mkdir(app_archive_path, mode);
685 if (errno != EEXIST) {
686 _E("unable to create directory for archiving,"
687 " error(%d)", errno);
688 return APP2EXT_ERROR_CREATE_DIRECTORY;
692 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
693 dir_detail = (app2ext_dir_details *)list->data;
694 if (dir_detail == NULL || dir_detail->name == NULL ||
695 dir_detail->type != APP2EXT_DIR_RO)
697 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
698 application_path, dir_detail->name);
699 if (ret < 0 || ret > sizeof(temp_dir_path)) {
701 return APP2EXT_ERROR_MMC_STATUS;
703 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
704 total_size += _app2sd_calculate_dir_size(temp_dir_path);
707 reqd_size = ((total_size) / (1024 * 1024)) + 2;
708 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
710 /* find avialable free memory in the MMC card */
711 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
713 _E("unable to get available free memory in MMC (%d)", ret);
714 return APP2EXT_ERROR_MMC_STATUS;
716 /* if avaialalbe free memory in MMC is less than
717 * required size + 5MB, return error
719 if (reqd_disk_size > free_mmc_mem) {
720 _E("insufficient memory in MMC for "
721 "application installation (%d)", ret);
722 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
724 /* create a loopback device */
725 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
726 (reqd_disk_size + PKG_BUF_SIZE));
728 _E("loopback node creation failed");
732 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
734 _E("dmcrypt setup device error(%d)", ret);
735 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
738 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
741 _E("dmcrypt open device error");
742 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
744 /* format the loopback file system */
745 ret = _app2sd_create_file_system(device_node);
747 _E("create ext4 filesystem failed");
748 ret = APP2EXT_ERROR_CREATE_FS;
752 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
753 dir_detail = (app2ext_dir_details *)list->data;
754 if (dir_detail == NULL || dir_detail->name == NULL ||
755 dir_detail->type != APP2EXT_DIR_RO)
757 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
758 application_path, dir_detail->name);
759 if (ret < 0 || ret > sizeof(temp_dir_path)) {
761 ret = APP2EXT_ERROR_MOVE;
764 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
765 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
767 _E("unable to copy from (%s) to (%s)",
768 temp_dir_path, app_archive_path);
773 /* mount the loopback encrypted pseudo device on
774 * application installation path as with Read Write permission
776 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
777 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
783 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
784 dir_detail = (app2ext_dir_details *)list->data;
785 if (dir_detail == NULL || dir_detail->name == NULL ||
786 dir_detail->type != APP2EXT_DIR_RO)
788 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
789 app_archive_path, dir_detail->name);
790 if (ret < 0 || ret > sizeof(temp_dir_path)) {
792 ret = APP2EXT_ERROR_COPY_DIRECTORY;
795 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
796 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
798 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
799 _E("unable to access (%s)", temp_dir_path);
801 err_str = strerror_r(errno, err_buf,
803 _E("unable to copy from (%s) to (%s),"
804 " error is (%s)", temp_dir_path,
805 app_mmc_path, err_str);
809 ret = _app2sd_delete_directory(temp_dir_path);
811 _E("unable to delete (%s)", temp_dir_path);
816 ret = _app2sd_delete_directory(app_archive_path);
818 _E("unable to delete (%s)", app_archive_path);
819 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
823 *image_path = strdup(loopback_device);
824 return APP2EXT_SUCCESS;
834 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
835 uid_t uid, char *mmc_path)
838 mode_t mode = DIR_PERMS;
839 char temp_dir_path[FILENAME_MAX];
840 char app_mmc_path[FILENAME_MAX];
841 char app_archive_path[FILENAME_MAX];
842 char application_path[FILENAME_MAX];
843 char loopback_device[FILENAME_MAX];
847 app2ext_dir_details *dir_detail;
849 int free_internal_mem;
850 unsigned long long temp = 0;
855 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
856 loopback_device, sizeof(loopback_device));
860 _app2sd_set_application_path(pkgid, uid, application_path,
861 sizeof(application_path));
863 /* check whether application is in external memory or not */
864 fp = fopen(loopback_device, "r+");
866 _E("application (%s) is not installed on SD Card",
868 return APP2EXT_ERROR_FILE_ABSENT;
872 /* find avialable free memory in the internal storage */
873 ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
876 _E("unable to get available free memory in internal (%d)", ret);
877 return APP2EXT_ERROR_MMC_STATUS;
880 fp = fopen(loopback_device, "r+");
882 _E("app entry is not present in SD card");
883 return APP2EXT_ERROR_INVALID_PACKAGE;
887 /* get installed app size*/
888 temp = _app2sd_calculate_file_size(loopback_device);
889 reqd_size = (int)((temp) / (1024 * 1024));
890 _D("reqd size is (%d)", reqd_size);
892 if (reqd_size == 0) {
893 _E("app entry is not present in SD Card");
894 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
897 _I("reqd size: (%d)MB, free internal mem: (%d)MB",
898 reqd_size, free_internal_mem);
900 /* if avaialalbe free memory in internal storage is
901 * less than required size, return error
903 if (reqd_size > free_internal_mem) {
904 _E("innsufficient memory in internal storage"
905 " for application installation (%d)", ret);
906 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
910 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
911 if (device_node == NULL) {
912 /* do loopback setup */
913 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
914 false, uid, &device_node);
916 _E("dmcrypt open device error(%d)", ret);
917 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
919 mount_type = MOUNT_TYPE_RW;
921 mount_type = MOUNT_TYPE_RW_REMOUNT;
924 ret = _app2sd_mount_app_content(application_path,
925 pkgid, device_node, mount_type,
926 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
929 ret = APP2EXT_ERROR_MOUNT_PATH;
933 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
935 if (ret < 0 || ret > sizeof(app_mmc_path)) {
940 ret = snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
942 if (ret < 0 || ret > sizeof(app_archive_path)) {
948 ret = mkdir(app_archive_path, mode);
950 if (errno != EEXIST) {
951 _E("unable to create directory for archiving,"
952 " error(%d)", errno);
953 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
958 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
959 dir_detail = (app2ext_dir_details *)list->data;
960 if (dir_detail == NULL || dir_detail->name == NULL ||
961 dir_detail->type != APP2EXT_DIR_RO)
964 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
965 app_mmc_path, dir_detail->name);
966 if (ret < 0 || ret > sizeof(temp_dir_path)) {
971 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
972 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
974 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
975 _E("unable to access (%s)", temp_dir_path);
977 err_str = strerror_r(errno, err_buf,
979 _E("unable to copy from (%s) to (%s),"
980 "error is (%s)", temp_dir_path,
981 app_archive_path, err_str);
985 /* delete the symbolic link files [bin, lib, res]*/
986 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
987 application_path, dir_detail->name);
988 if (ret < 0 || ret > sizeof(temp_dir_path)) {
993 _D("unlink, temp_dir_path(%s)", temp_dir_path);
994 ret = unlink(temp_dir_path);
996 if (errno == ENOENT) {
997 _W("(%s) does not exist", temp_dir_path);
999 _E("unable to remove the symbolic link file "
1000 "(%s), it is already unlinked",
1005 /* Copy content to destination */
1006 ret = snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
1007 app_archive_path, dir_detail->name);
1008 if (ret < 0 || ret > sizeof(temp_dir_path)) {
1009 _E("snprintf fail");
1013 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
1014 ret = _app2sd_copy_dir(temp_dir_path, application_path);
1016 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1017 _E("unable to access (%s)", temp_dir_path);
1019 err_str = strerror_r(errno, err_buf,
1021 _E("unable to copy from (%s) to (%s), "
1022 "error is (%s)", temp_dir_path,
1023 application_path, err_str);
1029 _D("copying file completed");
1030 ret = _app2sd_unmount_app_content(application_path);
1032 _E("unable to unmount SD directory for app (%s)", pkgid);
1034 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1036 _E("close dmcrypt device error(%d)", ret);
1038 ret = _app2sd_delete_loopback_device(loopback_device);
1040 _E("unable to delete the loopback device for (%s)", pkgid);
1042 ret = _app2sd_delete_directory(app_mmc_path);
1044 _E("unable to delete (%s)", app_mmc_path);
1046 ret = _app2sd_delete_directory(app_archive_path);
1048 _E("unable to delete (%s)", app_archive_path);
1050 /* remove passwrd from DB */
1051 ret = _app2sd_initialize_db();
1053 _E("app2sd db initialize failed");
1055 ret = _app2sd_remove_info_from_db(pkgid, uid);
1057 _E("cannot remove info from db");
1059 return APP2EXT_SUCCESS;
1068 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
1069 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
1073 switch (move_type) {
1074 case APP2EXT_MOVE_TO_EXT:
1075 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1076 uid, mmc_path, image_path);
1078 _E("move app to external memory failed(%d)", ret);
1082 case APP2EXT_MOVE_TO_PHONE:
1083 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1086 _E("move app to internal memory failed(%d)", ret);
1091 _E("invalid argument");
1092 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1098 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1100 char path[FILENAME_MAX];
1103 app2ext_dir_details *dir_detail;
1105 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1106 dir_detail = (app2ext_dir_details *)list->data;
1107 if (dir_detail == NULL || dir_detail->name == NULL ||
1108 dir_detail->type != APP2EXT_DIR_RO)
1111 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1112 ret = _app2sd_copy_dir(path, dest);
1114 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1115 _E("unable to access (%s)", path);
1117 _E("unable to copy from (%s) "
1118 "to (%s), errno is (%d)",
1120 return APP2EXT_ERROR_MOVE;
1125 return APP2EXT_SUCCESS;
1128 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1129 const char *temp_pkgid, const char *temp_application_path,
1130 const char *temp_loopback_device, GList *dir_list,
1131 char *dev_node, int size, uid_t uid)
1136 /* create a new loopback device */
1137 ret = _app2sd_create_loopback_device(temp_pkgid,
1138 temp_loopback_device, (size + PKG_BUF_SIZE));
1140 _E("package already present");
1144 /* perform loopback encryption setup */
1145 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1146 temp_loopback_device, uid);
1148 _E("dmcrypt duplicate encryption setup failed");
1149 _app2sd_delete_loopback_device(temp_loopback_device);
1150 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1153 /* format the loopback file system */
1154 ret = _app2sd_create_file_system(dev_node);
1156 _E("creating fs failed");
1157 err_res = APP2EXT_ERROR_CREATE_FS;
1160 _D("create filesystem SUCCESS");
1162 /* do mounting for new dev*/
1163 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1164 dev_node, MOUNT_TYPE_RW, dir_list,
1165 APP2SD_PRE_UPGRADE, uid);
1167 _E("remount failed");
1168 err_res = APP2EXT_ERROR_MOUNT_PATH;
1172 return APP2EXT_SUCCESS;
1176 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1178 _E("close dmcrypt device error(%d)", ret);
1179 _app2sd_delete_loopback_device(temp_loopback_device);
1186 int _app2sd_update_loopback_device_size(const char *pkgid,
1187 const char *loopback_device, const char *application_path,
1188 const char *temp_pkgid, const char *temp_loopback_device,
1189 const char *temp_application_path, int size, GList *dir_list,
1193 char *old_device_node;
1195 char app_mmc_path[FILENAME_MAX];
1196 char temp_app_mmc_path[FILENAME_MAX];
1199 ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1200 temp_application_path, temp_loopback_device,
1201 dir_list, NULL, size, uid);
1203 _E("creating duplicate device failed");
1207 /* get the associated device node for SD card applicatione */
1209 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1210 if (old_device_node == NULL) {
1211 /* do loopback setup */
1212 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1213 false, uid, &old_device_node);
1215 _E("dmcrypt open device error");
1216 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1219 mount_type = MOUNT_TYPE_RW;
1221 mount_type = MOUNT_TYPE_RW_REMOUNT;
1225 ret = _app2sd_mount_app_content(application_path, pkgid,
1226 old_device_node, mount_type, dir_list,
1227 APP2SD_PRE_UPGRADE, uid);
1229 _E("remount failed");
1230 err_res = APP2EXT_ERROR_MOUNT_PATH;
1232 free(old_device_node);
1234 snprintf(app_mmc_path, sizeof(app_mmc_path),
1235 "%s/.mmc", application_path);
1236 snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1237 "%s/.mmc", temp_application_path);
1239 ret = _app2sd_copy_ro_content(app_mmc_path,
1240 temp_app_mmc_path, dir_list);
1242 _E("copy ro content failed");
1246 ret = _app2sd_unmount_app_content(application_path);
1248 _E("unable to unmount the SD application");
1249 err_res = APP2EXT_ERROR_UNMOUNT;
1252 ret = _app2sd_unmount_app_content(temp_application_path);
1254 _E("unable to unmount the SD application");
1255 err_res = APP2EXT_ERROR_UNMOUNT;
1259 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1261 _E("close dmcrypt device error(%d)", ret);
1262 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1266 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1268 _E("close dmcrypt device error(%d)", ret);
1269 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1273 ret = _app2sd_delete_directory(loopback_device);
1275 _E("unable to delete (%s)", loopback_device);
1276 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1280 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1282 _E("unable to rename (%s)", temp_loopback_device);
1283 err_res = APP2EXT_ERROR_MOVE;
1287 ret = _app2sd_delete_directory(temp_application_path);
1289 _E("unable to delete (%s)", temp_application_path);
1290 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1294 return APP2EXT_SUCCESS;
1297 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1299 _E("close dmcrypt device error(%d)", ret);
1301 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1303 _E("close dmcrypt device error(%d)", ret);
1305 _app2sd_delete_loopback_device(temp_loopback_device);
1307 ret = _app2sd_delete_directory(temp_application_path);
1309 _E("unable to delete (%s)", temp_application_path);
1314 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1315 const char *loopback_device, uid_t uid)
1319 /* unmount the loopback encrypted pseudo device from
1320 * the application installation path
1322 ret = _app2sd_unmount_app_content(application_path);
1324 _W("unable to unmount the app content (%d)", ret);
1326 /* detach the loopback encryption setup for the application */
1327 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1329 _W("close dmcrypt device error (%d)", ret);
1331 /* delete the loopback device from the SD card */
1332 ret = _app2sd_delete_loopback_device(loopback_device);
1334 _W("unable to detach the loopback encryption setup for "
1337 /* delete symlink */
1338 _app2sd_delete_symlink(application_path);
1340 /* remove passwrd from DB */
1341 ret = _app2sd_initialize_db();
1343 _W("app2sd db initialize failed");
1345 ret = _app2sd_remove_info_from_db(pkgid, uid);
1347 _W("cannot remove info from db");