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];
98 if (pkgid == NULL || loopback_device == NULL) {
99 _E("invalid argument");
100 return APP2EXT_ERROR_INVALID_ARGUMENTS;
103 /* get password for dmcrypt encryption */
104 ret = _app2sd_initialize_db();
106 _E("app2sd db initialize failed");
107 return APP2EXT_ERROR_DB_INITIALIZE;
110 passwd = _app2sd_get_password_from_db(pkgid, uid);
111 if (passwd == NULL) {
113 _E("no password found for (%s)", pkgid);
114 return APP2EXT_ERROR_SQLITE_REGISTRY;
116 passwd = _app2sd_generate_password();
117 if (passwd == NULL) {
118 _E("unable to generate password");
119 return APP2EXT_ERROR_PASSWD_GENERATION;
122 ret = _app2sd_set_info_in_db(pkgid, passwd, loopback_device,
125 _E("unable to save password");
127 return APP2EXT_ERROR_SQLITE_REGISTRY;
131 snprintf(dmcrypt_setup_cmd, sizeof(dmcrypt_setup_cmd),
132 "/bin/echo '%s' | /sbin/cryptsetup -q -i %d "
133 "-c aes-cbc-lmk -s %d --align-payload=8 luksFormat %s",
134 passwd, DMCRYPT_ITER_TIME, DMCRYPT_KEY_LEN,
137 ret = system(dmcrypt_setup_cmd);
139 strerror_r(errno, err_buf, sizeof(err_buf));
140 _E("Error setting up dmcrypt on app2sd file, error:%s, ret:%d",
142 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
148 int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
149 bool is_dup, uid_t uid, char **dev_node)
153 char dmcrypt_open_cmd[BUF_SIZE];
154 char dev_name[BUF_SIZE];
157 if (pkgid == NULL || loopback_device == NULL) {
158 _E("invalid argument");
159 return APP2EXT_ERROR_INVALID_ARGUMENTS;
163 snprintf(dev_name, sizeof(dev_name), "%s.new_%d", pkgid, uid);
165 snprintf(dev_name, sizeof(dev_name), "%s_%d", pkgid, uid);
167 /* get password for dmcrypt encryption */
168 ret = _app2sd_initialize_db();
170 _E("app2sd db initialize failed");
171 return APP2EXT_ERROR_DB_INITIALIZE;
174 passwd = _app2sd_get_password_from_db(pkgid, uid);
175 if (passwd == NULL) {
176 _E("no password found for [%s]", pkgid);
177 return APP2EXT_ERROR_SQLITE_REGISTRY;
180 if (_app2sd_check_is_luks_device(loopback_device) == 0) {
181 _W("legacy image format!");
182 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
183 "/bin/echo '%s' | /sbin/cryptsetup "
184 "-M plain -c aes-cbc-plain -h plain open %s %s",
185 passwd, loopback_device, dev_name);
187 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
188 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen "
190 passwd, loopback_device, dev_name);
194 ret = system(dmcrypt_open_cmd);
196 strerror_r(errno, buf, sizeof(buf));
197 _E("error opening dmcrypt device, error: [%s]", buf);
198 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
201 snprintf(buf, sizeof(buf), "/dev/mapper/%s", dev_name);
202 *dev_node = strdup(buf);
203 if (*dev_node == NULL) {
204 _E("memory alloc failed");
205 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
211 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
214 char dev_node[BUF_SIZE];
215 char dmcrypt_close_cmd[BUF_SIZE];
216 char err_buf[BUF_SIZE];
220 _E("invalid argument");
221 return APP2EXT_ERROR_INVALID_ARGUMENTS;
224 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
226 _W("no associated device node(%s_%d) found", pkgid, uid);
227 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
232 snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
233 snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
234 "/sbin/cryptsetup -q luksClose %s", dev_node);
235 ret = system(dmcrypt_close_cmd);
237 strerror_r(errno, err_buf, sizeof(err_buf));
238 _E("error closing dmcrypt on app2sd file: %s", err_buf);
239 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
245 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
250 snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
251 if (access(buf, F_OK) == 0) {
252 dev_node = strdup(buf);
253 if (dev_node == NULL) {
254 _E("memory alloc failed");
257 _D("device_node: (%s)", dev_node);
260 _D("can not access dev_node(%s), errno(%d)", buf, errno);
265 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
266 const char *temp_loopback_device, uid_t uid)
271 if (pkgid == NULL || temp_loopback_device == NULL) {
272 _E("invalid argument");
276 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
279 _E("dmcrypt setup device error(%d)", ret);
283 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
286 _E("dmcrypt open device error");
293 int _app2sd_create_loopback_device(const char *pkgid,
294 const char *loopback_device, int size)
297 char command[FILENAME_MAX];
300 const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
301 "bs=1M", buff, NULL };
303 if (pkgid == NULL || size <= 0) {
304 _E("invalid argument");
305 return APP2EXT_ERROR_INVALID_ARGUMENTS;
308 fp = fopen(loopback_device, "r+");
310 _W("encrypted file already exists (%s)", loopback_device);
312 return APP2EXT_ERROR_PKG_EXISTS;
315 snprintf(command, sizeof(command), "of=%s", loopback_device);
316 snprintf(buff, sizeof(buff), "count=%d", size);
318 ret = _xsystem(argv);
320 _E("command (%s) failed, ret(%d), errno(%d)",
321 command, ret, errno);
326 int _app2sd_delete_loopback_device(const char *loopback_device)
330 ret = unlink(loopback_device);
332 if (errno == ENOENT) {
333 _W("unable to access file (%s)", loopback_device);
335 _E("unable to delete (%s)", loopback_device);
336 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
340 return APP2EXT_SUCCESS;
343 int _app2sd_create_file_system(const char *device_path)
348 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
350 if (device_path == NULL) {
352 return APP2EXT_ERROR_INVALID_ARGUMENTS;
355 /* Format the filesystem [create a filesystem]*/
356 fp = fopen(device_path, "r+");
358 strerror_r(errno, err_buf, sizeof(err_buf));
359 _E("unable to access (%s) error is (%d, %s)",
360 device_path, errno, err_buf);
361 return APP2EXT_ERROR_ACCESS_FILE;
365 ret = _xsystem(argv);
367 strerror_r(errno, err_buf, sizeof(err_buf));
368 _E("creating file system failed, error is (%s)", err_buf);
369 return APP2EXT_ERROR_CREATE_FS;
374 static int _app2sd_create_dir_with_link(const char *application_path,
375 const char *pkgid, const char *dir_name, uid_t uid)
378 char app_dir_mmc_path[FILENAME_MAX];
379 char app_dir_path[FILENAME_MAX];
381 snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
382 application_path, dir_name);
383 snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
384 application_path, dir_name);
386 ret = _app2sd_make_directory(app_dir_mmc_path, uid);
388 _E("create directory failed");
389 return APP2EXT_ERROR_CREATE_DIRECTORY;
392 ret = symlink(app_dir_mmc_path, app_dir_path);
394 if (errno == EEXIST) {
395 _D("file with symlink name present (%s)", app_dir_path);
397 _E("symbolic link creation failed, error: %d", errno);
398 return APP2EXT_ERROR_CREATE_SYMLINK;
402 return APP2EXT_SUCCESS;
405 static int _app2sd_create_directory_entry(const char *application_path,
406 const char *pkgid, GList *dir_list, uid_t uid)
410 app2ext_dir_details *dir_detail;
412 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
413 dir_detail = (app2ext_dir_details *)list->data;
414 if (dir_detail == NULL || dir_detail->name == NULL ||
415 dir_detail->type != APP2EXT_DIR_RO)
417 ret = _app2sd_create_dir_with_link(application_path,
418 pkgid, dir_detail->name, uid);
422 return APP2EXT_SUCCESS;
425 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
426 const char *dev, int mount_type, GList *dir_list,
427 app2sd_cmd cmd, uid_t uid)
431 char app_mmc_path[FILENAME_MAX];
432 char temp_path[FILENAME_MAX];
434 struct timespec time = {
436 .tv_nsec = 1000 * 1000 * 200
438 char mountflags_str[BUF_SIZE];
439 const char *argv_mount[] = { "/bin/app2sd-mount-helper", dev,
440 app_mmc_path, FS_TYPE, mountflags_str, NULL };
443 _E("input param is NULL (%s)", dev);
444 return APP2EXT_ERROR_INVALID_ARGUMENTS;
447 /* check directory existence */
448 fd = open(application_path, O_RDONLY | O_DIRECTORY);
450 _E("path(%s) error(%d)", application_path, errno);
451 return APP2EXT_ERROR_OPEN_DIR;
455 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
457 fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
459 _E("path(%s) error(%d)", app_mmc_path, errno);
460 return APP2EXT_ERROR_OPEN_DIR;
464 nanosleep(&time, NULL); /* 200ms sleep */
465 _D("give a delay for mount");
467 switch (mount_type) {
469 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
470 MS_MGC_VAL | MS_RDONLY | MS_NOSUID);
471 ret = _xsystem(argv_mount);
473 _E("read only mount failed, errono is (%d), "
474 "dev is (%s) path is (%s)",
475 errno, dev, app_mmc_path);
476 ret = APP2EXT_ERROR_MOUNT;
480 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
481 MS_MGC_VAL | MS_NOSUID);
482 ret = _xsystem(argv_mount);
484 _E("read write mount failed, errono is (%d)", errno);
485 ret = APP2EXT_ERROR_MOUNT;
488 case MOUNT_TYPE_RW_NOEXEC:
489 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
490 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID);
491 ret = _xsystem(argv_mount);
493 _E("rwnx mount failed errono is (%d)", errno);
494 ret = APP2EXT_ERROR_MOUNT;
497 case MOUNT_TYPE_RD_REMOUNT:
498 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
499 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT |
501 ret = _xsystem(argv_mount);
503 _E("read remount failed errono is (%d)", errno);
504 ret = APP2EXT_ERROR_MOUNT;
507 case MOUNT_TYPE_RW_REMOUNT:
508 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
509 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID);
510 ret = _xsystem(argv_mount);
511 strerror_r(errno, err_buf, sizeof(err_buf));
513 _E("read write remount failed errono(%d), errstr(%s)",
515 ret = APP2EXT_ERROR_MOUNT;
519 _E("invalid mount type");
523 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
524 cmd == APP2SD_PRE_UPGRADE) {
525 ret = _app2sd_create_directory_entry(application_path,
526 pkgid, dir_list, uid);
529 if (mount_type != MOUNT_TYPE_RD &&
530 mount_type != MOUNT_TYPE_RD_REMOUNT) {
531 /* change lost+found permission */
532 snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
534 ret = _app2sd_make_directory(temp_path, uid);
536 _E("create directory(%s) failed", temp_path);
537 return APP2EXT_ERROR_CREATE_DIRECTORY;
544 int _app2sd_unmount_app_content(const char *application_path)
547 char app_mmc_path[FILENAME_MAX];
550 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
552 ret = umount(app_mmc_path);
554 strerror_r(errno, err_buf, sizeof(err_buf));
555 _D("unable to umount the dir, ret(%d) error(%d, %s)",
556 ret, errno, err_buf);
562 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
567 ret = _app2sd_copy_dir(src_path, arch_path);
568 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
569 strerror_r(errno, err_buf, sizeof(err_buf));
570 _E("unable to copy from (%s) to (%s), err is (%s)",
571 src_path, arch_path, err_buf);
572 return APP2EXT_ERROR_MOVE;
575 ret = _app2sd_delete_directory(src_path);
577 _E("unable to delete (%s)", src_path);
578 return APP2EXT_ERROR_DELETE_DIRECTORY;
584 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
585 uid_t uid, char *mmc_path, char **image_path)
588 mode_t mode = DIR_PERMS;
589 char temp_dir_path[FILENAME_MAX];
590 char app_mmc_path[FILENAME_MAX];
591 char app_archive_path[FILENAME_MAX];
592 char application_path[FILENAME_MAX];
593 char loopback_device[FILENAME_MAX];
594 unsigned long long total_size = 0;
601 app2ext_dir_details *dir_detail;
604 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
605 loopback_device, sizeof(loopback_device));
609 _app2sd_set_application_path(pkgid, uid, application_path,
610 sizeof(application_path));
612 /* check whether application is in external memory or not */
613 fp = fopen(loopback_device, "r+");
615 _W("Already %s entry is present in the SD Card, "
616 "delete entry and go on without return", pkgid);
618 _app2sd_force_clean(pkgid, application_path, loopback_device,
622 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
624 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
627 ret = mkdir(app_mmc_path, mode);
629 if (errno != EEXIST) {
630 _E("unable to create directory for archiving,"
631 " error(%d)", errno);
632 return APP2EXT_ERROR_CREATE_DIRECTORY;
636 ret = mkdir(app_archive_path, mode);
638 if (errno != EEXIST) {
639 _E("unable to create directory for archiving,"
640 " error(%d)", errno);
641 return APP2EXT_ERROR_CREATE_DIRECTORY;
645 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
646 dir_detail = (app2ext_dir_details *)list->data;
647 if (dir_detail == NULL || dir_detail->name == NULL ||
648 dir_detail->type != APP2EXT_DIR_RO)
650 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
651 application_path, dir_detail->name);
652 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
653 total_size += _app2sd_calculate_dir_size(temp_dir_path);
656 reqd_size = ((total_size) / (1024 * 1024)) + 2;
657 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
659 /* find avialable free memory in the MMC card */
660 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
662 _E("unable to get available free memory in MMC (%d)", ret);
663 return APP2EXT_ERROR_MMC_STATUS;
665 /* if avaialalbe free memory in MMC is less than
666 * required size + 5MB, return error
668 if (reqd_disk_size > free_mmc_mem) {
669 _E("insufficient memory in MMC for "
670 "application installation (%d)", ret);
671 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
673 /* create a loopback device */
674 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
675 (reqd_disk_size + PKG_BUF_SIZE));
677 _E("loopback node creation failed");
681 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
683 _E("dmcrypt setup device error(%d)", ret);
684 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
687 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
690 _E("dmcrypt open device error");
691 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
693 /* format the loopback file system */
694 ret = _app2sd_create_file_system(device_node);
696 _E("create ext4 filesystem failed");
697 ret = APP2EXT_ERROR_CREATE_FS;
701 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
702 dir_detail = (app2ext_dir_details *)list->data;
703 if (dir_detail == NULL || dir_detail->name == NULL ||
704 dir_detail->type != APP2EXT_DIR_RO)
706 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
707 application_path, dir_detail->name);
708 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
709 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
711 _E("unable to copy from (%s) to (%s)",
712 temp_dir_path, app_archive_path);
717 /* mount the loopback encrypted pseudo device on
718 * application installation path as with Read Write permission
720 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
721 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
727 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
728 dir_detail = (app2ext_dir_details *)list->data;
729 if (dir_detail == NULL || dir_detail->name == NULL ||
730 dir_detail->type != APP2EXT_DIR_RO)
732 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
733 app_archive_path, dir_detail->name);
734 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
735 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
737 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
738 _E("unable to access (%s)", temp_dir_path);
740 strerror_r(errno, err_buf, sizeof(err_buf));
741 _E("unable to copy from (%s) to (%s),"
742 " error is (%s)", temp_dir_path,
743 app_mmc_path, err_buf);
747 ret = _app2sd_delete_directory(temp_dir_path);
749 _E("unable to delete (%s)", temp_dir_path);
754 ret = _app2sd_delete_directory(app_archive_path);
756 _E("unable to delete (%s)", app_archive_path);
757 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
761 *image_path = strdup(loopback_device);
762 return APP2EXT_SUCCESS;
772 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
773 uid_t uid, char *mmc_path)
776 mode_t mode = DIR_PERMS;
777 char temp_dir_path[FILENAME_MAX];
778 char app_mmc_path[FILENAME_MAX];
779 char app_archive_path[FILENAME_MAX];
780 char application_path[FILENAME_MAX];
781 char loopback_device[FILENAME_MAX];
785 app2ext_dir_details *dir_detail;
787 int free_internal_mem;
788 unsigned long long temp = 0;
792 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
793 loopback_device, sizeof(loopback_device));
797 _app2sd_set_application_path(pkgid, uid, application_path,
798 sizeof(application_path));
800 /* check whether application is in external memory or not */
801 fp = fopen(loopback_device, "r+");
803 _E("application (%s) is not installed on SD Card",
805 return APP2EXT_ERROR_FILE_ABSENT;
809 /* find avialable free memory in the internal storage */
810 ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
813 _E("unable to get available free memory in internal (%d)", ret);
814 return APP2EXT_ERROR_MMC_STATUS;
817 fp = fopen(loopback_device, "r+");
819 _E("app entry is not present in SD card");
820 return APP2EXT_ERROR_INVALID_PACKAGE;
824 /* get installed app size*/
825 temp = _app2sd_calculate_file_size(loopback_device);
826 reqd_size = (int)((temp) / (1024 * 1024));
827 _D("reqd size is (%d)", reqd_size);
829 if (reqd_size == 0) {
830 _E("app entry is not present in SD Card");
831 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
834 _I("reqd size: (%d)MB, free internal mem: (%d)MB",
835 reqd_size, free_internal_mem);
837 /* if avaialalbe free memory in internal storage is
838 * less than required size, return error
840 if (reqd_size > free_internal_mem) {
841 _E("innsufficient memory in internal storage"
842 " for application installation (%d)", ret);
843 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
847 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
848 if (device_node == NULL) {
849 /* do loopback setup */
850 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
851 false, uid, &device_node);
853 _E("dmcrypt open device error(%d)", ret);
854 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
856 mount_type = MOUNT_TYPE_RW;
858 mount_type = MOUNT_TYPE_RW_REMOUNT;
861 ret = _app2sd_mount_app_content(application_path,
862 pkgid, device_node, mount_type,
863 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
866 ret = APP2EXT_ERROR_MOUNT_PATH;
870 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
872 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
875 ret = mkdir(app_archive_path, mode);
877 if (errno != EEXIST) {
878 _E("unable to create directory for archiving,"
879 " error(%d)", errno);
880 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
885 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
886 dir_detail = (app2ext_dir_details *)list->data;
887 if (dir_detail == NULL || dir_detail->name == NULL ||
888 dir_detail->type != APP2EXT_DIR_RO)
891 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
892 app_mmc_path, dir_detail->name);
893 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
894 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
896 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
897 _E("unable to access (%s)", temp_dir_path);
899 strerror_r(errno, err_buf, sizeof(err_buf));
900 _E("unable to copy from (%s) to (%s),"
901 "error is (%s)", temp_dir_path,
902 app_archive_path, err_buf);
906 /* delete the symbolic link files [bin, lib, res]*/
907 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
908 application_path, dir_detail->name);
909 _D("unlink, temp_dir_path(%s)", temp_dir_path);
910 ret = unlink(temp_dir_path);
912 if (errno == ENOENT) {
913 _W("(%s) does not exist", temp_dir_path);
915 _E("unable to remove the symbolic link file "
916 "(%s), it is already unlinked",
921 /* Copy content to destination */
922 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
923 app_archive_path, dir_detail->name);
924 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
925 ret = _app2sd_copy_dir(temp_dir_path, application_path);
927 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
928 _E("unable to access (%s)", temp_dir_path);
930 strerror_r(errno, err_buf, sizeof(err_buf));
931 _E("unable to copy from (%s) to (%s), "
932 "error is (%s)", temp_dir_path,
933 application_path, err_buf);
939 _D("copying file completed");
940 ret = _app2sd_unmount_app_content(application_path);
942 _E("unable to unmount SD directory for app (%s)", pkgid);
944 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
946 _E("close dmcrypt device error(%d)", ret);
948 ret = _app2sd_delete_loopback_device(loopback_device);
950 _E("unable to delete the loopback device for (%s)", pkgid);
952 ret = _app2sd_delete_directory(app_mmc_path);
954 _E("unable to delete (%s)", app_mmc_path);
956 ret = _app2sd_delete_directory(app_archive_path);
958 _E("unable to delete (%s)", app_archive_path);
960 /* remove passwrd from DB */
961 ret = _app2sd_initialize_db();
963 _E("app2sd db initialize failed");
965 ret = _app2sd_remove_info_from_db(pkgid, uid);
967 _E("cannot remove info from db");
969 return APP2EXT_SUCCESS;
978 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
979 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
984 case APP2EXT_MOVE_TO_EXT:
985 ret = _app2sd_move_app_to_external(pkgid, dir_list,
986 uid, mmc_path, image_path);
988 _E("move app to external memory failed(%d)", ret);
992 case APP2EXT_MOVE_TO_PHONE:
993 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
996 _E("move app to internal memory failed(%d)", ret);
1001 _E("invalid argument");
1002 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1008 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1010 char path[FILENAME_MAX];
1013 app2ext_dir_details *dir_detail;
1015 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1016 dir_detail = (app2ext_dir_details *)list->data;
1017 if (dir_detail == NULL || dir_detail->name == NULL ||
1018 dir_detail->type != APP2EXT_DIR_RO)
1021 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1022 ret = _app2sd_copy_dir(path, dest);
1024 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1025 _E("unable to access (%s)", path);
1027 _E("unable to copy from (%s) "
1028 "to (%s), errno is (%d)",
1030 return APP2EXT_ERROR_MOVE;
1035 return APP2EXT_SUCCESS;
1038 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1039 const char *temp_pkgid, const char *temp_application_path,
1040 const char *temp_loopback_device, GList *dir_list,
1041 char *dev_node, int size, uid_t uid)
1046 /* create a new loopback device */
1047 ret = _app2sd_create_loopback_device(temp_pkgid,
1048 temp_loopback_device, (size + PKG_BUF_SIZE));
1050 _E("package already present");
1054 /* perform loopback encryption setup */
1055 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1056 temp_loopback_device, uid);
1058 _E("dmcrypt duplicate encryption setup failed");
1059 _app2sd_delete_loopback_device(temp_loopback_device);
1060 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1063 /* format the loopback file system */
1064 ret = _app2sd_create_file_system(dev_node);
1066 _E("creating fs failed");
1067 err_res = APP2EXT_ERROR_CREATE_FS;
1070 _D("create filesystem SUCCESS");
1072 /* do mounting for new dev*/
1073 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1074 dev_node, MOUNT_TYPE_RW, dir_list,
1075 APP2SD_PRE_UPGRADE, uid);
1077 _E("remount failed");
1078 err_res = APP2EXT_ERROR_MOUNT_PATH;
1082 return APP2EXT_SUCCESS;
1086 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1088 _E("close dmcrypt device error(%d)", ret);
1089 _app2sd_delete_loopback_device(temp_loopback_device);
1096 int _app2sd_update_loopback_device_size(const char *pkgid,
1097 const char *loopback_device, const char *application_path,
1098 const char *temp_pkgid, const char *temp_loopback_device,
1099 const char *temp_application_path, int size, GList *dir_list,
1103 char *old_device_node;
1105 char app_mmc_path[FILENAME_MAX];
1106 char temp_app_mmc_path[FILENAME_MAX];
1109 ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1110 temp_application_path, temp_loopback_device,
1111 dir_list, NULL, size, uid);
1113 _E("creating duplicate device failed");
1117 /* get the associated device node for SD card applicatione */
1119 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1120 if (old_device_node == NULL) {
1121 /* do loopback setup */
1122 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1123 false, uid, &old_device_node);
1125 _E("dmcrypt open device error");
1126 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1129 mount_type = MOUNT_TYPE_RW;
1131 mount_type = MOUNT_TYPE_RW_REMOUNT;
1135 ret = _app2sd_mount_app_content(application_path, pkgid,
1136 old_device_node, mount_type, dir_list,
1137 APP2SD_PRE_UPGRADE, uid);
1139 _E("remount failed");
1140 err_res = APP2EXT_ERROR_MOUNT_PATH;
1143 snprintf(app_mmc_path, sizeof(app_mmc_path),
1144 "%s/.mmc", application_path);
1145 snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1146 "%s/.mmc", temp_application_path);
1148 ret = _app2sd_copy_ro_content(app_mmc_path,
1149 temp_app_mmc_path, dir_list);
1151 _E("copy ro content failed");
1155 ret = _app2sd_unmount_app_content(application_path);
1157 _E("unable to unmount the SD application");
1158 err_res = APP2EXT_ERROR_UNMOUNT;
1161 ret = _app2sd_unmount_app_content(temp_application_path);
1163 _E("unable to unmount the SD application");
1164 err_res = APP2EXT_ERROR_UNMOUNT;
1168 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1170 _E("close dmcrypt device error(%d)", ret);
1171 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1175 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1177 _E("close dmcrypt device error(%d)", ret);
1178 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1182 ret = _app2sd_delete_directory(loopback_device);
1184 _E("unable to delete (%s)", loopback_device);
1185 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1189 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1191 _E("unable to rename (%s)", temp_loopback_device);
1192 err_res = APP2EXT_ERROR_MOVE;
1196 ret = _app2sd_delete_directory(temp_application_path);
1198 _E("unable to delete (%s)", temp_application_path);
1199 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1203 return APP2EXT_SUCCESS;
1206 if (old_device_node)
1207 free(old_device_node);
1209 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1211 _E("close dmcrypt device error(%d)", ret);
1213 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1215 _E("close dmcrypt device error(%d)", ret);
1217 _app2sd_delete_loopback_device(temp_loopback_device);
1219 ret = _app2sd_delete_directory(temp_application_path);
1221 _E("unable to delete (%s)", temp_application_path);
1226 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1227 const char *loopback_device, uid_t uid)
1231 /* unmount the loopback encrypted pseudo device from
1232 * the application installation path
1234 ret = _app2sd_unmount_app_content(application_path);
1236 _W("unable to unmount the app content (%d)", ret);
1238 /* detach the loopback encryption setup for the application */
1239 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1241 _W("close dmcrypt device error (%d)", ret);
1243 /* delete the loopback device from the SD card */
1244 ret = _app2sd_delete_loopback_device(loopback_device);
1246 _W("unable to detach the loopback encryption setup for "
1249 /* delete symlink */
1250 _app2sd_delete_symlink(application_path);
1252 /* remove passwrd from DB */
1253 ret = _app2sd_initialize_db();
1255 _W("app2sd db initialize failed");
1257 ret = _app2sd_remove_info_from_db(pkgid, uid);
1259 _W("cannot remove info from db");