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)
156 char dmcrypt_open_cmd[BUF_SIZE];
157 char dev_name[BUF_SIZE];
161 if (pkgid == NULL || loopback_device == NULL) {
162 _E("invalid argument");
163 return APP2EXT_ERROR_INVALID_ARGUMENTS;
167 snprintf(dev_name, sizeof(dev_name), "%s.new_%d", pkgid, uid);
169 snprintf(dev_name, sizeof(dev_name), "%s_%d", pkgid, uid);
171 /* get password for dmcrypt encryption */
172 ret = _app2sd_initialize_db();
174 _E("app2sd db initialize failed");
175 return APP2EXT_ERROR_DB_INITIALIZE;
178 passwd = _app2sd_get_password_from_db(pkgid, uid);
179 if (passwd == NULL) {
180 _E("no password found for [%s]", pkgid);
181 return APP2EXT_ERROR_SQLITE_REGISTRY;
184 if (_app2sd_check_is_luks_device(loopback_device) == 0) {
185 _W("legacy image format!");
186 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
187 "/bin/echo '%s' | /sbin/cryptsetup "
188 "-M plain -c aes-cbc-plain -h plain open %s %s",
189 passwd, loopback_device, dev_name);
191 snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
192 "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen "
194 passwd, loopback_device, dev_name);
198 ret = system(dmcrypt_open_cmd);
200 err_str = strerror_r(errno, buf, sizeof(buf));
201 _E("error opening dmcrypt device, error: [%s]", err_str);
202 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
205 snprintf(buf, sizeof(buf), "/dev/mapper/%s", dev_name);
206 *dev_node = strdup(buf);
207 if (*dev_node == NULL) {
208 _E("memory alloc failed");
209 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
215 int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid)
218 char dev_node[BUF_SIZE];
219 char dmcrypt_close_cmd[BUF_SIZE];
220 char err_buf[BUF_SIZE];
225 _E("invalid argument");
226 return APP2EXT_ERROR_INVALID_ARGUMENTS;
229 t_dev_node = _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
231 _W("no associated device node(%s_%d) found", pkgid, uid);
232 return APP2EXT_ERROR_DMCRYPT_DEVICE_UNAVAILABLE;
237 snprintf(dev_node, sizeof(dev_node), "/dev/mapper/%s_%d", pkgid, uid);
238 snprintf(dmcrypt_close_cmd, sizeof(dmcrypt_close_cmd),
239 "/sbin/cryptsetup -q luksClose %s", dev_node);
240 ret = system(dmcrypt_close_cmd);
242 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
243 _E("error closing dmcrypt on app2sd file: %s", err_str);
244 return APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
250 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
255 snprintf(buf, sizeof(buf), "/dev/mapper/%s_%d", pkgid, uid);
256 if (access(buf, F_OK) == 0) {
257 dev_node = strdup(buf);
258 if (dev_node == NULL) {
259 _E("memory alloc failed");
262 _D("device_node: (%s)", dev_node);
265 _D("can not access dev_node(%s), errno(%d)", buf, errno);
270 char *_app2sd_dmcrypt_duplicate_encryption_setup(const char *pkgid,
271 const char *temp_loopback_device, uid_t uid)
276 if (pkgid == NULL || temp_loopback_device == NULL) {
277 _E("invalid argument");
281 ret = _app2sd_dmcrypt_setup_device(pkgid, temp_loopback_device, true,
284 _E("dmcrypt setup device error(%d)", ret);
288 ret = _app2sd_dmcrypt_open_device(pkgid, temp_loopback_device, true,
291 _E("dmcrypt open device error");
298 int _app2sd_create_loopback_device(const char *pkgid,
299 const char *loopback_device, int size)
302 char command[FILENAME_MAX];
305 const char *argv[] = { "/bin/dd", "if=/dev/zero", command,
306 "bs=1M", buff, NULL };
308 if (pkgid == NULL || size <= 0) {
309 _E("invalid argument");
310 return APP2EXT_ERROR_INVALID_ARGUMENTS;
313 fp = fopen(loopback_device, "r+");
315 _W("encrypted file already exists (%s)", loopback_device);
317 return APP2EXT_ERROR_PKG_EXISTS;
320 snprintf(command, sizeof(command), "of=%s", loopback_device);
321 snprintf(buff, sizeof(buff), "count=%d", size);
323 ret = _xsystem(argv);
325 _E("command (%s) failed, ret(%d), errno(%d)",
326 command, ret, errno);
331 int _app2sd_delete_loopback_device(const char *loopback_device)
335 ret = unlink(loopback_device);
337 if (errno == ENOENT) {
338 _W("unable to access file (%s)", loopback_device);
340 _E("unable to delete (%s)", loopback_device);
341 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
345 return APP2EXT_SUCCESS;
348 int _app2sd_create_file_system(const char *device_path)
354 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
356 if (device_path == NULL) {
358 return APP2EXT_ERROR_INVALID_ARGUMENTS;
361 /* Format the filesystem [create a filesystem]*/
362 fp = fopen(device_path, "r+");
364 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
365 _E("unable to access (%s) error is (%d, %s)",
366 device_path, errno, err_buf);
367 return APP2EXT_ERROR_ACCESS_FILE;
371 ret = _xsystem(argv);
373 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
374 _E("creating file system failed, error is (%s)", err_str);
375 return APP2EXT_ERROR_CREATE_FS;
380 static int _app2sd_create_dir_with_link(const char *application_path,
381 const char *pkgid, const char *dir_name, uid_t uid)
384 char app_dir_mmc_path[FILENAME_MAX];
385 char app_dir_path[FILENAME_MAX];
387 snprintf(app_dir_mmc_path, sizeof(app_dir_mmc_path), "%s/.mmc/%s",
388 application_path, dir_name);
389 snprintf(app_dir_path, sizeof(app_dir_path), "%s/%s",
390 application_path, dir_name);
392 ret = _app2sd_make_directory(app_dir_mmc_path, uid);
394 _E("create directory failed");
395 return APP2EXT_ERROR_CREATE_DIRECTORY;
398 ret = symlink(app_dir_mmc_path, app_dir_path);
400 if (errno == EEXIST) {
401 _D("file with symlink name present (%s)", app_dir_path);
403 _E("symbolic link creation failed, error: %d", errno);
404 return APP2EXT_ERROR_CREATE_SYMLINK;
408 return APP2EXT_SUCCESS;
411 static int _app2sd_create_directory_entry(const char *application_path,
412 const char *pkgid, GList *dir_list, uid_t uid)
416 app2ext_dir_details *dir_detail;
418 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
419 dir_detail = (app2ext_dir_details *)list->data;
420 if (dir_detail == NULL || dir_detail->name == NULL ||
421 dir_detail->type != APP2EXT_DIR_RO)
423 ret = _app2sd_create_dir_with_link(application_path,
424 pkgid, dir_detail->name, uid);
428 return APP2EXT_SUCCESS;
431 int _app2sd_mount_app_content(const char *application_path, const char *pkgid,
432 const char *dev, int mount_type, GList *dir_list,
433 app2sd_cmd cmd, uid_t uid)
437 char app_mmc_path[FILENAME_MAX];
438 char temp_path[FILENAME_MAX];
441 struct timespec time = {
443 .tv_nsec = 1000 * 1000 * 200
445 char mountflags_str[BUF_SIZE];
446 const char *argv_mount[] = { "/bin/app2sd-mount-helper", dev,
447 app_mmc_path, FS_TYPE, mountflags_str, NULL };
450 _E("input param is NULL (%s)", dev);
451 return APP2EXT_ERROR_INVALID_ARGUMENTS;
454 /* check directory existence */
455 fd = open(application_path, O_RDONLY | O_DIRECTORY);
457 _E("path(%s) error(%d)", application_path, errno);
458 return APP2EXT_ERROR_OPEN_DIR;
462 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
464 fd = open(app_mmc_path, O_RDONLY | O_DIRECTORY);
466 _E("path(%s) error(%d)", app_mmc_path, errno);
467 return APP2EXT_ERROR_OPEN_DIR;
471 nanosleep(&time, NULL); /* 200ms sleep */
472 _D("give a delay for mount");
474 switch (mount_type) {
476 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
477 MS_MGC_VAL | MS_RDONLY | MS_NOSUID);
478 ret = _xsystem(argv_mount);
480 _E("read only mount failed, errono is (%d), "
481 "dev is (%s) path is (%s)",
482 ret, dev, app_mmc_path);
483 ret = APP2EXT_ERROR_MOUNT;
487 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
488 MS_MGC_VAL | MS_NOSUID);
489 ret = _xsystem(argv_mount);
491 _E("read write mount failed, errno is (%d)", ret);
492 ret = APP2EXT_ERROR_MOUNT;
495 case MOUNT_TYPE_RW_NOEXEC:
496 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
497 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID);
498 ret = _xsystem(argv_mount);
500 _E("rwnx mount failed errno is (%d)", ret);
501 ret = APP2EXT_ERROR_MOUNT;
504 case MOUNT_TYPE_RD_REMOUNT:
505 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
506 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT |
508 ret = _xsystem(argv_mount);
510 _E("read remount failed errno is (%d)", ret);
511 ret = APP2EXT_ERROR_MOUNT;
514 case MOUNT_TYPE_RW_REMOUNT:
515 snprintf(mountflags_str, sizeof(mountflags_str), "%u",
516 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID);
517 ret = _xsystem(argv_mount);
518 err_str = strerror_r(ret, err_buf, sizeof(err_buf));
520 _E("read write remount failed errno(%d), errstr(%s)",
522 ret = APP2EXT_ERROR_MOUNT;
526 _E("invalid mount type");
530 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC ||
531 cmd == APP2SD_PRE_UPGRADE) {
532 ret = _app2sd_create_directory_entry(application_path,
533 pkgid, dir_list, uid);
536 if (mount_type != MOUNT_TYPE_RD &&
537 mount_type != MOUNT_TYPE_RD_REMOUNT) {
538 /* change lost+found permission */
539 snprintf(temp_path, sizeof(temp_path), "%s/lost+found",
541 ret = _app2sd_make_directory(temp_path, uid);
543 _E("create directory(%s) failed", temp_path);
544 return APP2EXT_ERROR_CREATE_DIRECTORY;
551 int _app2sd_unmount_app_content(const char *application_path)
554 char app_mmc_path[FILENAME_MAX];
558 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
560 ret = umount(app_mmc_path);
562 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
563 _D("unable to umount the dir, ret(%d) error(%d, %s)",
564 ret, errno, err_str);
570 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
576 ret = _app2sd_copy_dir(src_path, arch_path);
577 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
578 err_str = strerror_r(errno, err_buf, sizeof(err_buf));
579 _E("unable to copy from (%s) to (%s), err is (%s)",
580 src_path, arch_path, err_str);
581 return APP2EXT_ERROR_MOVE;
584 ret = _app2sd_delete_directory(src_path);
586 _E("unable to delete (%s)", src_path);
587 return APP2EXT_ERROR_DELETE_DIRECTORY;
593 static int _app2sd_move_app_to_external(const char *pkgid, GList *dir_list,
594 uid_t uid, char *mmc_path, char **image_path)
597 mode_t mode = DIR_PERMS;
598 char temp_dir_path[FILENAME_MAX];
599 char app_mmc_path[FILENAME_MAX];
600 char app_archive_path[FILENAME_MAX];
601 char application_path[FILENAME_MAX];
602 char loopback_device[FILENAME_MAX];
603 unsigned long long total_size = 0;
610 app2ext_dir_details *dir_detail;
614 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
615 loopback_device, sizeof(loopback_device));
619 _app2sd_set_application_path(pkgid, uid, application_path,
620 sizeof(application_path));
622 /* check whether application is in external memory or not */
623 fp = fopen(loopback_device, "r+");
625 _W("Already %s entry is present in the SD Card, "
626 "delete entry and go on without return", pkgid);
628 _app2sd_force_clean(pkgid, application_path, loopback_device,
632 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
634 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
637 ret = mkdir(app_mmc_path, mode);
639 if (errno != EEXIST) {
640 _E("unable to create directory for archiving,"
641 " error(%d)", errno);
642 return APP2EXT_ERROR_CREATE_DIRECTORY;
646 ret = mkdir(app_archive_path, mode);
648 if (errno != EEXIST) {
649 _E("unable to create directory for archiving,"
650 " error(%d)", errno);
651 return APP2EXT_ERROR_CREATE_DIRECTORY;
655 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
656 dir_detail = (app2ext_dir_details *)list->data;
657 if (dir_detail == NULL || dir_detail->name == NULL ||
658 dir_detail->type != APP2EXT_DIR_RO)
660 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
661 application_path, dir_detail->name);
662 _D("cal size of app dirs, temp_dir_path(%s)", temp_dir_path);
663 total_size += _app2sd_calculate_dir_size(temp_dir_path);
666 reqd_size = ((total_size) / (1024 * 1024)) + 2;
667 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
669 /* find avialable free memory in the MMC card */
670 ret = _app2sd_get_available_free_memory(mmc_path, &free_mmc_mem);
672 _E("unable to get available free memory in MMC (%d)", ret);
673 return APP2EXT_ERROR_MMC_STATUS;
675 /* if avaialalbe free memory in MMC is less than
676 * required size + 5MB, return error
678 if (reqd_disk_size > free_mmc_mem) {
679 _E("insufficient memory in MMC for "
680 "application installation (%d)", ret);
681 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
683 /* create a loopback device */
684 ret = _app2sd_create_loopback_device(pkgid, loopback_device,
685 (reqd_disk_size + PKG_BUF_SIZE));
687 _E("loopback node creation failed");
691 ret = _app2sd_dmcrypt_setup_device(pkgid, loopback_device, false, uid);
693 _E("dmcrypt setup device error(%d)", ret);
694 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
697 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device, false,
700 _E("dmcrypt open device error");
701 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
703 /* format the loopback file system */
704 ret = _app2sd_create_file_system(device_node);
706 _E("create ext4 filesystem failed");
707 ret = APP2EXT_ERROR_CREATE_FS;
711 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
712 dir_detail = (app2ext_dir_details *)list->data;
713 if (dir_detail == NULL || dir_detail->name == NULL ||
714 dir_detail->type != APP2EXT_DIR_RO)
716 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
717 application_path, dir_detail->name);
718 _D("app2archive, temp_dir_path(%s)", temp_dir_path);
719 ret = _app2sd_move_to_archive(temp_dir_path, app_archive_path);
721 _E("unable to copy from (%s) to (%s)",
722 temp_dir_path, app_archive_path);
727 /* mount the loopback encrypted pseudo device on
728 * application installation path as with Read Write permission
730 ret = _app2sd_mount_app_content(application_path, pkgid, device_node,
731 MOUNT_TYPE_RW, dir_list, APP2SD_MOVE_APP_TO_MMC, uid);
737 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
738 dir_detail = (app2ext_dir_details *)list->data;
739 if (dir_detail == NULL || dir_detail->name == NULL ||
740 dir_detail->type != APP2EXT_DIR_RO)
742 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
743 app_archive_path, dir_detail->name);
744 _D("archive2mmc, temp_dir_path(%s)", temp_dir_path);
745 ret = _app2sd_copy_dir(temp_dir_path, app_mmc_path);
747 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
748 _E("unable to access (%s)", temp_dir_path);
750 err_str = strerror_r(errno, err_buf,
752 _E("unable to copy from (%s) to (%s),"
753 " error is (%s)", temp_dir_path,
754 app_mmc_path, err_str);
758 ret = _app2sd_delete_directory(temp_dir_path);
760 _E("unable to delete (%s)", temp_dir_path);
765 ret = _app2sd_delete_directory(app_archive_path);
767 _E("unable to delete (%s)", app_archive_path);
768 ret = APP2EXT_ERROR_DELETE_DIRECTORY;
772 *image_path = strdup(loopback_device);
773 return APP2EXT_SUCCESS;
783 static int _app2sd_move_app_to_internal(const char *pkgid, GList *dir_list,
784 uid_t uid, char *mmc_path)
787 mode_t mode = DIR_PERMS;
788 char temp_dir_path[FILENAME_MAX];
789 char app_mmc_path[FILENAME_MAX];
790 char app_archive_path[FILENAME_MAX];
791 char application_path[FILENAME_MAX];
792 char loopback_device[FILENAME_MAX];
796 app2ext_dir_details *dir_detail;
798 int free_internal_mem;
799 unsigned long long temp = 0;
804 ret = _app2sd_get_loopback_device_path(mmc_path, pkgid, uid,
805 loopback_device, sizeof(loopback_device));
809 _app2sd_set_application_path(pkgid, uid, application_path,
810 sizeof(application_path));
812 /* check whether application is in external memory or not */
813 fp = fopen(loopback_device, "r+");
815 _E("application (%s) is not installed on SD Card",
817 return APP2EXT_ERROR_FILE_ABSENT;
821 /* find avialable free memory in the internal storage */
822 ret = _app2sd_get_available_free_memory(INTERNAL_STORAGE_PATH,
825 _E("unable to get available free memory in internal (%d)", ret);
826 return APP2EXT_ERROR_MMC_STATUS;
829 fp = fopen(loopback_device, "r+");
831 _E("app entry is not present in SD card");
832 return APP2EXT_ERROR_INVALID_PACKAGE;
836 /* get installed app size*/
837 temp = _app2sd_calculate_file_size(loopback_device);
838 reqd_size = (int)((temp) / (1024 * 1024));
839 _D("reqd size is (%d)", reqd_size);
841 if (reqd_size == 0) {
842 _E("app entry is not present in SD Card");
843 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
846 _I("reqd size: (%d)MB, free internal mem: (%d)MB",
847 reqd_size, free_internal_mem);
849 /* if avaialalbe free memory in internal storage is
850 * less than required size, return error
852 if (reqd_size > free_internal_mem) {
853 _E("innsufficient memory in internal storage"
854 " for application installation (%d)", ret);
855 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
859 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
860 if (device_node == NULL) {
861 /* do loopback setup */
862 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
863 false, uid, &device_node);
865 _E("dmcrypt open device error(%d)", ret);
866 return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
868 mount_type = MOUNT_TYPE_RW;
870 mount_type = MOUNT_TYPE_RW_REMOUNT;
873 ret = _app2sd_mount_app_content(application_path,
874 pkgid, device_node, mount_type,
875 dir_list, APP2SD_MOVE_APP_TO_PHONE, uid);
878 ret = APP2EXT_ERROR_MOUNT_PATH;
882 snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
884 snprintf(app_archive_path, sizeof(app_archive_path), "%s/.archive",
887 ret = mkdir(app_archive_path, mode);
889 if (errno != EEXIST) {
890 _E("unable to create directory for archiving,"
891 " error(%d)", errno);
892 ret = APP2EXT_ERROR_CREATE_DIRECTORY;
897 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
898 dir_detail = (app2ext_dir_details *)list->data;
899 if (dir_detail == NULL || dir_detail->name == NULL ||
900 dir_detail->type != APP2EXT_DIR_RO)
903 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
904 app_mmc_path, dir_detail->name);
905 _D("mmc2archive, temp_dir_path(%s)", temp_dir_path);
906 ret = _app2sd_copy_dir(temp_dir_path, app_archive_path);
908 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
909 _E("unable to access (%s)", temp_dir_path);
911 err_str = strerror_r(errno, err_buf,
913 _E("unable to copy from (%s) to (%s),"
914 "error is (%s)", temp_dir_path,
915 app_archive_path, err_str);
919 /* delete the symbolic link files [bin, lib, res]*/
920 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
921 application_path, dir_detail->name);
922 _D("unlink, temp_dir_path(%s)", temp_dir_path);
923 ret = unlink(temp_dir_path);
925 if (errno == ENOENT) {
926 _W("(%s) does not exist", temp_dir_path);
928 _E("unable to remove the symbolic link file "
929 "(%s), it is already unlinked",
934 /* Copy content to destination */
935 snprintf(temp_dir_path, sizeof(temp_dir_path), "%s/%s",
936 app_archive_path, dir_detail->name);
937 _D("archive2app, temp_dir_path(%s)", temp_dir_path);
938 ret = _app2sd_copy_dir(temp_dir_path, application_path);
940 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
941 _E("unable to access (%s)", temp_dir_path);
943 err_str = strerror_r(errno, err_buf,
945 _E("unable to copy from (%s) to (%s), "
946 "error is (%s)", temp_dir_path,
947 application_path, err_str);
953 _D("copying file completed");
954 ret = _app2sd_unmount_app_content(application_path);
956 _E("unable to unmount SD directory for app (%s)", pkgid);
958 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
960 _E("close dmcrypt device error(%d)", ret);
962 ret = _app2sd_delete_loopback_device(loopback_device);
964 _E("unable to delete the loopback device for (%s)", pkgid);
966 ret = _app2sd_delete_directory(app_mmc_path);
968 _E("unable to delete (%s)", app_mmc_path);
970 ret = _app2sd_delete_directory(app_archive_path);
972 _E("unable to delete (%s)", app_archive_path);
974 /* remove passwrd from DB */
975 ret = _app2sd_initialize_db();
977 _E("app2sd db initialize failed");
979 ret = _app2sd_remove_info_from_db(pkgid, uid);
981 _E("cannot remove info from db");
983 return APP2EXT_SUCCESS;
992 int _app2sd_usr_move_app(const char *pkgid, app2ext_move_type move_type,
993 GList *dir_list, uid_t uid, char *mmc_path, char **image_path)
998 case APP2EXT_MOVE_TO_EXT:
999 ret = _app2sd_move_app_to_external(pkgid, dir_list,
1000 uid, mmc_path, image_path);
1002 _E("move app to external memory failed(%d)", ret);
1006 case APP2EXT_MOVE_TO_PHONE:
1007 ret = _app2sd_move_app_to_internal(pkgid, dir_list,
1010 _E("move app to internal memory failed(%d)", ret);
1015 _E("invalid argument");
1016 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1022 int _app2sd_copy_ro_content(const char *src, const char *dest, GList *dir_list)
1024 char path[FILENAME_MAX];
1027 app2ext_dir_details *dir_detail;
1029 for (list = g_list_first(dir_list); list; list = g_list_next(list)) {
1030 dir_detail = (app2ext_dir_details *)list->data;
1031 if (dir_detail == NULL || dir_detail->name == NULL ||
1032 dir_detail->type != APP2EXT_DIR_RO)
1035 snprintf(path, sizeof(path), "%s/%s", src, dir_detail->name);
1036 ret = _app2sd_copy_dir(path, dest);
1038 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1039 _E("unable to access (%s)", path);
1041 _E("unable to copy from (%s) "
1042 "to (%s), errno is (%d)",
1044 return APP2EXT_ERROR_MOVE;
1049 return APP2EXT_SUCCESS;
1052 int _app2sd_duplicate_device(const char *pkgid, const char *loopback_device,
1053 const char *temp_pkgid, const char *temp_application_path,
1054 const char *temp_loopback_device, GList *dir_list,
1055 char *dev_node, int size, uid_t uid)
1060 /* create a new loopback device */
1061 ret = _app2sd_create_loopback_device(temp_pkgid,
1062 temp_loopback_device, (size + PKG_BUF_SIZE));
1064 _E("package already present");
1068 /* perform loopback encryption setup */
1069 dev_node = _app2sd_dmcrypt_duplicate_encryption_setup(pkgid,
1070 temp_loopback_device, uid);
1072 _E("dmcrypt duplicate encryption setup failed");
1073 _app2sd_delete_loopback_device(temp_loopback_device);
1074 return APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE;
1077 /* format the loopback file system */
1078 ret = _app2sd_create_file_system(dev_node);
1080 _E("creating fs failed");
1081 err_res = APP2EXT_ERROR_CREATE_FS;
1084 _D("create filesystem SUCCESS");
1086 /* do mounting for new dev*/
1087 ret = _app2sd_mount_app_content(temp_application_path, pkgid,
1088 dev_node, MOUNT_TYPE_RW, dir_list,
1089 APP2SD_PRE_UPGRADE, uid);
1091 _E("remount failed");
1092 err_res = APP2EXT_ERROR_MOUNT_PATH;
1096 return APP2EXT_SUCCESS;
1100 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1102 _E("close dmcrypt device error(%d)", ret);
1103 _app2sd_delete_loopback_device(temp_loopback_device);
1110 int _app2sd_update_loopback_device_size(const char *pkgid,
1111 const char *loopback_device, const char *application_path,
1112 const char *temp_pkgid, const char *temp_loopback_device,
1113 const char *temp_application_path, int size, GList *dir_list,
1117 char *old_device_node;
1119 char app_mmc_path[FILENAME_MAX];
1120 char temp_app_mmc_path[FILENAME_MAX];
1123 ret = _app2sd_duplicate_device(pkgid, loopback_device, temp_pkgid,
1124 temp_application_path, temp_loopback_device,
1125 dir_list, NULL, size, uid);
1127 _E("creating duplicate device failed");
1131 /* get the associated device node for SD card applicatione */
1133 _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
1134 if (old_device_node == NULL) {
1135 /* do loopback setup */
1136 ret = _app2sd_dmcrypt_open_device(pkgid, loopback_device,
1137 false, uid, &old_device_node);
1139 _E("dmcrypt open device error");
1140 err_res = APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
1143 mount_type = MOUNT_TYPE_RW;
1145 mount_type = MOUNT_TYPE_RW_REMOUNT;
1149 ret = _app2sd_mount_app_content(application_path, pkgid,
1150 old_device_node, mount_type, dir_list,
1151 APP2SD_PRE_UPGRADE, uid);
1153 _E("remount failed");
1154 err_res = APP2EXT_ERROR_MOUNT_PATH;
1156 free(old_device_node);
1158 snprintf(app_mmc_path, sizeof(app_mmc_path),
1159 "%s/.mmc", application_path);
1160 snprintf(temp_app_mmc_path, sizeof(temp_app_mmc_path),
1161 "%s/.mmc", temp_application_path);
1163 ret = _app2sd_copy_ro_content(app_mmc_path,
1164 temp_app_mmc_path, dir_list);
1166 _E("copy ro content failed");
1170 ret = _app2sd_unmount_app_content(application_path);
1172 _E("unable to unmount the SD application");
1173 err_res = APP2EXT_ERROR_UNMOUNT;
1176 ret = _app2sd_unmount_app_content(temp_application_path);
1178 _E("unable to unmount the SD application");
1179 err_res = APP2EXT_ERROR_UNMOUNT;
1183 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1185 _E("close dmcrypt device error(%d)", ret);
1186 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1190 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1192 _E("close dmcrypt device error(%d)", ret);
1193 err_res = APP2EXT_ERROR_CLOSE_DMCRYPT_DEVICE;
1197 ret = _app2sd_delete_directory(loopback_device);
1199 _E("unable to delete (%s)", loopback_device);
1200 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1204 ret = _app2sd_rename_dir(temp_loopback_device, loopback_device);
1206 _E("unable to rename (%s)", temp_loopback_device);
1207 err_res = APP2EXT_ERROR_MOVE;
1211 ret = _app2sd_delete_directory(temp_application_path);
1213 _E("unable to delete (%s)", temp_application_path);
1214 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1218 return APP2EXT_SUCCESS;
1221 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1223 _E("close dmcrypt device error(%d)", ret);
1225 ret = _app2sd_dmcrypt_close_device(temp_pkgid, uid);
1227 _E("close dmcrypt device error(%d)", ret);
1229 _app2sd_delete_loopback_device(temp_loopback_device);
1231 ret = _app2sd_delete_directory(temp_application_path);
1233 _E("unable to delete (%s)", temp_application_path);
1238 int _app2sd_force_clean(const char *pkgid, const char *application_path,
1239 const char *loopback_device, uid_t uid)
1243 /* unmount the loopback encrypted pseudo device from
1244 * the application installation path
1246 ret = _app2sd_unmount_app_content(application_path);
1248 _W("unable to unmount the app content (%d)", ret);
1250 /* detach the loopback encryption setup for the application */
1251 ret = _app2sd_dmcrypt_close_device(pkgid, uid);
1253 _W("close dmcrypt device error (%d)", ret);
1255 /* delete the loopback device from the SD card */
1256 ret = _app2sd_delete_loopback_device(loopback_device);
1258 _W("unable to detach the loopback encryption setup for "
1261 /* delete symlink */
1262 _app2sd_delete_symlink(application_path);
1264 /* remove passwrd from DB */
1265 ret = _app2sd_initialize_db();
1267 _W("app2sd db initialize failed");
1269 ret = _app2sd_remove_info_from_db(pkgid, uid);
1271 _W("cannot remove info from db");