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.
24 #include <app2sd_internals.h>
25 #include <app2sd_interface.h>
27 #include <sys/xattr.h>
28 #include <sys/types.h>
38 #include <openssl/sha.h>
42 #include <privilege-control.h>
43 #include <sys/statvfs.h>
45 extern int app2sd_force_clean(const char *pkgid);
48 ########### Internal APIs ##################
50 static int _app2sd_setup_path(const char *pkgid, const char *dirpath,
51 int apppathtype, const char *groupid)
55 if (groupid == NULL) {
56 ret = perm_app_setup_path(pkgid, dirpath, apppathtype);
57 app2ext_print( "[smack] app_setup_path(), result = [%d]", ret);
59 ret = perm_app_setup_path(pkgid, dirpath, apppathtype, groupid);
60 app2ext_print( "[smack] app_setup_path(), result = [%d]", ret);
68 static int _app2sd_apply_app_smack(const char *pkgid, GList* dir_list, const char *groupid)
70 int ret = APP2EXT_SUCCESS;
72 app2ext_dir_details* dir_detail = NULL;
73 char path[FILENAME_MAX] = { 0, };
75 list = g_list_first(dir_list);
77 dir_detail = (app2ext_dir_details *)list->data;
78 if (dir_detail && dir_detail->name
79 && dir_detail->type == APP2EXT_DIR_RO) {
80 snprintf(path, FILENAME_MAX, "%s%s/%s",APP_INSTALLATION_PATH, pkgid, dir_detail->name);
81 ret = _app2sd_setup_path(pkgid, path, PERM_APP_PATH_ANY_LABEL, groupid);
83 app2ext_print ("App2Sd Error : unable to smack %s\n", path);
84 return APP2EXT_ERROR_MOVE;
87 list = g_list_next(list);
90 return APP2EXT_SUCCESS;
95 static int _app2sd_apply_mmc_smack(const char *pkgid, GList* dir_list, const char *groupid)
97 int ret = APP2EXT_SUCCESS;
99 app2ext_dir_details* dir_detail = NULL;
100 char path[FILENAME_MAX] = { 0, };
102 list = g_list_first(dir_list);
104 dir_detail = (app2ext_dir_details *)list->data;
105 if (dir_detail && dir_detail->name
106 && dir_detail->type == APP2EXT_DIR_RO) {
107 snprintf(path, FILENAME_MAX, "%s%s/.mmc/%s",APP_INSTALLATION_PATH, pkgid, dir_detail->name);
109 ret = _app2sd_setup_path(pkgid, path, PERM_APP_PATH_ANY_LABEL, groupid);
111 app2ext_print ("App2Sd Error : unable to smack %s\n", path);
112 return APP2EXT_ERROR_MOVE;
115 list = g_list_next(list);
118 return APP2EXT_SUCCESS;
122 char *_app2sd_find_associated_device_node(const char *pkgid)
124 char *ret_result = NULL;
127 char app_path[FILENAME_MAX] = { '\0' };
128 char dev[FILENAME_MAX] = {0,};
129 char *devnode = NULL;
130 snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH,
132 app2ext_print("sdcard app_path = (%s)\n", app_path);
133 result = (char *)_app2sd_find_associated_device(app_path);
134 if (result == NULL) {
135 app2ext_print("App2SD info! there is no the associated File with [%s]\n", pkgid);
138 /* process the string*/
139 app2ext_print("result = (%s)\n", result);
140 snprintf(dev, FILENAME_MAX-1, "%s", result);
141 if (strstr(dev, "/dev") == NULL) {
142 app2ext_print("App2SD Error! Unable to find the associated File\n");
147 char *saveptr = NULL;
148 ret_result = strtok_r(dev, delims, &saveptr);
150 devnode = strdup(ret_result);
156 char *_app2sd_create_loopdevice_node(void)
158 char *ret_result = NULL;
159 mode_t mode = DIR_PERMS;
161 int ret = APP2EXT_SUCCESS;
165 result = (char *)_app2sd_find_free_device();
166 /* validate the result */
167 if (result == NULL || strstr(result, "/dev") == NULL) {
168 app2ext_print("No device found, creating device node...\n");
175 char dev_path[BUF_SIZE] = { 0, };
176 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
177 while ((fp = fopen(dev_path, "r+")) != NULL) {
179 snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count);
180 app2ext_print("next dev path for checking is %s\n",
184 app2ext_print("Device node candidate is %s \n", dev_path);
186 dev_node = makedev(DEV_MAJOR, count);
187 ret = mknod(dev_path, S_IFBLK | mode, dev_node);
190 ("Error while creating the device node: errno is %d\n",
194 ret_result = (char *)malloc(strlen(dev_path) + 1);
195 if (ret_result == NULL) {
196 app2ext_print("Unable to allocate memory\n");
199 memset(ret_result, '\0', strlen(dev_path) + 1);
200 memcpy(ret_result, dev_path, strlen(dev_path));
202 ret_result = (char *)malloc(strlen(result) + 1);
203 if (ret_result == NULL) {
204 app2ext_print("Malloc failed!\n");
209 memset(ret_result, '\0', strlen(result) + 1);
210 if (strlen(result) > 0) {
211 memcpy(ret_result, result, strlen(result) - 1);
220 char *_app2sd_do_loopback_encryption_setup(const char *pkgid)
222 int ret = APP2EXT_SUCCESS;
224 char app_path[FILENAME_MAX] = { '\0' };
226 char *device_node = NULL;
228 app2ext_print("App2Sd Error: Invalid argument\n");
232 snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH,
234 /* Get password for loopback encryption */
235 ret = _app2sd_initialize_db();
237 app2ext_print("\n app2sd db initialize failed");
240 if ((passwd = _app2sd_get_password_from_db(pkgid)) == NULL) {
241 passwd = (char *)_app2sd_generate_password(pkgid);
242 if (NULL == passwd) {
244 ("App2Sd Error: Unable to generate password\n");
247 app2ext_print("Password is %s\n", passwd);
248 if ((ret = _app2sd_set_password_in_db(pkgid,
251 ("App2Sd Error: Unable to save password\n");
259 /* Get Free device node*/
260 device_node = _app2sd_create_loopdevice_node();
261 if (NULL == device_node) {
265 ("App2Sd Error: Unable to find free loopback node\n");
268 result = (char *)_app2sd_encrypt_device(device_node, app_path, passwd);
269 if (result == NULL) {
270 app2ext_print("App2Sd Error: Encryption failed!\n\n");
283 char *_app2sd_do_loopback_duplicate_encryption_setup(const char *pkgid, const char * dup_appname)
285 int ret = APP2EXT_SUCCESS;
287 char app_path[FILENAME_MAX] = { '\0' };
289 char *device_node = NULL;
290 if (pkgid == NULL || dup_appname == NULL) {
291 app2ext_print("App2Sd Error: Invalid argument\n");
295 snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH,
297 /* Get password for loopback encryption */
298 ret = _app2sd_initialize_db();
300 app2ext_print("\n app2sd db initialize failed");
303 if ((passwd = _app2sd_get_password_from_db(pkgid)) == NULL) {
304 passwd = (char *)_app2sd_generate_password(pkgid);
305 if (NULL == passwd) {
307 ("App2Sd Error: Unable to generate password\n");
310 app2ext_print("Password is %s\n", passwd);
311 if ((ret = _app2sd_set_password_in_db(pkgid,
314 ("App2Sd Error: Unable to save password\n");
322 /* Get Free device node*/
323 device_node = _app2sd_create_loopdevice_node();
324 if (NULL == device_node) {
328 ("App2Sd Error: Unable to find free loopback node\n");
331 result = (char *)_app2sd_encrypt_device(device_node, app_path, passwd);
332 if (result == NULL) {
333 app2ext_print("App2Sd Error: Encryption failed!\n\n");
338 if (strlen(result) == 0) {
345 app2ext_print("App2Sd Error: Error is %s\n", result);
356 int _app2sd_remove_loopback_encryption_setup(const char *pkgid)
358 int ret = APP2EXT_SUCCESS;
360 char *dev_node = NULL;
361 if ((dev_node = _app2sd_find_associated_device_node(pkgid)) == NULL) {
362 app2ext_print("Unable to find the association\n");
363 ret = APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE;
365 result = (char *)_app2sd_detach_loop_device(dev_node);
366 if (result == NULL) {
367 app2ext_print("App2sd Error: Error in detaching\n");
368 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
380 int _app2sd_remove_all_loopback_encryption_setups(const char *pkgid)
382 int ret = APP2EXT_SUCCESS;
384 char *dev_node = NULL;
386 if ((dev_node = _app2sd_find_associated_device_node(pkgid)) == NULL) {
387 app2ext_print("finish to find the association\n");
388 ret = APP2EXT_SUCCESS;
392 app2ext_print("find node :: %s \n", dev_node);
394 result = (char *)_app2sd_detach_loop_device(dev_node);
395 if (result == NULL) {
396 app2ext_print("App2sd Error: Error in detaching\n");
397 ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
411 int _app2sd_create_loopback_device(const char *pkgid, int size)
413 int ret = APP2EXT_SUCCESS;
414 char command[FILENAME_MAX] = { 0, };
415 mode_t mode = DIR_PERMS;
416 char external_storage_path[FILENAME_MAX] = { 0, };
417 char buff[BUF_SIZE] = { 0, };
418 char app_path[FILENAME_MAX] = { 0, };
421 if (NULL == pkgid || size <= 0) {
422 app2ext_print("App2Sd Error: Invalid argument\n");
423 return APP2EXT_ERROR_INVALID_ARGUMENTS;
425 snprintf(command, FILENAME_MAX, "of=%s%s", APP2SD_PATH,
427 snprintf(buff, BUF_SIZE, "count=%d", size);
428 const char *argv1[] =
429 { "dd", "if=/dev/zero", command, "bs=1M", buff, NULL };
430 snprintf(external_storage_path, FILENAME_MAX, "%s",
432 ret = mkdir(external_storage_path, mode);
434 if (errno != EEXIST) {
436 ("App2sd Error : Create directory failed, error no is %d\n",
438 return APP2EXT_ERROR_CREATE_DIRECTORY;
441 snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH,
443 if ((fp = fopen(app_path, "r+")) != NULL) {
444 app2ext_print("Application already exists %s\n", app_path);
446 return APP2EXT_ERROR_PKG_EXISTS;
449 ret = _xsystem(argv1);
451 app2ext_print("App2Sd Error : command \"%s\" failed \n",
458 int _app2sd_delete_loopback_device(const char *pkgid)
460 int ret = APP2EXT_SUCCESS;
461 char loopback_device[FILENAME_MAX] = { 0, };
463 snprintf(loopback_device, FILENAME_MAX, "%s%s", APP2SD_PATH,
466 ret = unlink(loopback_device);
468 if (errno == ENOENT) {
469 app2ext_print("Unable to access file %s\n", loopback_device);
471 app2ext_print("Unable to delete %s\n", loopback_device);
472 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
478 int _app2sd_create_file_system(const char *device_path)
480 int ret = APP2EXT_SUCCESS;
482 char err_buf[1024] = {0,};
484 if (device_path == NULL) {
485 app2ext_print("App2Sd Error: invalid param [NULL]\n");
486 return APP2EXT_ERROR_INVALID_ARGUMENTS;
489 /* Format the filesystem [create a filesystem]*/
490 const char *argv[] = { "/sbin/mkfs.ext4", device_path, NULL };
491 fp = fopen(device_path, "r+");
493 strerror_r(errno, err_buf, sizeof(err_buf));
495 ("App2sd Error: Unable to access %s [System errono is %d.....%s]\n",
496 device_path, errno, err_buf);
497 return APP2EXT_ERROR_ACCESS_FILE;
501 ret = _xsystem(argv);
503 strerror_r(errno, err_buf, sizeof(err_buf));
505 ("App2Sd Error : creating file system failed [System error is %s\n",
507 return APP2EXT_ERROR_CREATE_FS;
512 static int _app2sd_create_dir_with_link(const char *pkgid,
513 const char *dir_name)
515 mode_t mode = DIR_PERMS;
516 int ret = APP2EXT_SUCCESS;
517 char app_dir_mmc_path[FILENAME_MAX] = { 0, };
518 char app_dir_path[FILENAME_MAX] = { 0, };
519 snprintf(app_dir_mmc_path, FILENAME_MAX, "%s%s/.mmc/%s",APP_INSTALLATION_PATH,
521 snprintf(app_dir_path, FILENAME_MAX, "%s%s/%s", APP_INSTALLATION_PATH, pkgid,
524 ret = mkdir(app_dir_mmc_path, mode);
526 if (errno != EEXIST) {
528 ("App2sd Error : Create directory failed, error no is %d\n",
530 return APP2EXT_ERROR_CREATE_DIRECTORY;
534 if ((ret = symlink(app_dir_mmc_path, app_dir_path)) < 0) {
535 if (errno == EEXIST) {
537 ("App2sd : File with Symlink name present %s\n",
541 ("A2Sd Error : Symbolic link creation failed, error no is %d\n",
543 return APP2EXT_ERROR_CREATE_SYMLINK;
549 ret = _app2sd_setup_path(pkgid, app_dir_path, PERM_APP_PATH_ANY_LABEL, pkgid);
551 app2ext_print ("App2Sd Error : unable to smack %s\n", app_dir_path);
552 return APP2EXT_ERROR_MOVE;
555 ret = _app2sd_setup_path(pkgid, app_dir_mmc_path, PERM_APP_PATH_ANY_LABEL, pkgid);
557 app2ext_print ("App2Sd Error : unable to smack %s\n", app_dir_mmc_path);
558 return APP2EXT_ERROR_MOVE;
565 int _app2sd_create_directory_entry(const char *pkgid, GList* dir_list)
567 int ret = APP2EXT_SUCCESS;
568 char app_dir_path[FILENAME_MAX] = { 0, };
570 app2ext_dir_details* dir_detail = NULL;
572 snprintf(app_dir_path, FILENAME_MAX, "%s%s", APP_INSTALLATION_PATH,
575 list = g_list_first(dir_list);
577 dir_detail = (app2ext_dir_details *)list->data;
578 if (dir_detail && dir_detail->name
579 && dir_detail->type == APP2EXT_DIR_RO) {
580 ret = _app2sd_create_dir_with_link(pkgid, dir_detail->name);
585 list = g_list_next(list);
587 return APP2EXT_SUCCESS;
593 * _app2sd_mount_app_content
594 This function is to create the path for mmc and mount the content
595 Example usage: _app2sd_mount_app_content("deb.com.samsung.helloworld","/dev/loop0",MOUNT_TYPE_RD)
597 int _app2sd_mount_app_content(const char *pkgid, const char *dev,
598 int mount_type, GList* dir_list, app2sd_cmd cmd)
600 int ret = APP2EXT_SUCCESS;
601 mode_t mode = DIR_PERMS;
602 char app_dir_path[FILENAME_MAX] = { 0, };
603 char app_dir_mmc_path[FILENAME_MAX] = { 0, };
604 struct timespec time = {
606 .tv_nsec = 1000 * 1000 * 200
609 if (NULL == pkgid || NULL == dev) {
610 app2ext_print("App2Sd Error : Input param is NULL %s %s \n",
612 return APP2EXT_ERROR_INVALID_ARGUMENTS;
614 snprintf(app_dir_path, FILENAME_MAX, "%s%s", APP_INSTALLATION_PATH, pkgid);
615 ret = mkdir(app_dir_path, mode);
617 if (errno != EEXIST) {
619 ("App2Sd Error : Create directory failed, error no is %d\n",
621 return APP2EXT_ERROR_CREATE_DIRECTORY;
624 snprintf(app_dir_mmc_path, FILENAME_MAX, "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid);
625 ret = mkdir(app_dir_mmc_path, mode);
627 if (errno != EEXIST) {
629 ("App2Sd Error : Create directory failed, error no is %d\n",
631 return APP2EXT_ERROR_CREATE_DIRECTORY;
635 nanosleep(&time, NULL); /* 200ms sleep */
636 app2ext_print ("App2Sd info : give a delay for mount\n");
638 switch (mount_type) {
642 mount(dev, app_dir_mmc_path, FS_TYPE,
643 MS_MGC_VAL | MS_RDONLY | MS_NOSUID, NULL)) < 0) {
645 ("App2Sd Error : Read Only Mount failed [System Erro no is %d], dev is %s path is %s\n",
646 errno, dev, app_dir_mmc_path);
647 ret = APP2EXT_ERROR_MOUNT;
654 mount(dev, app_dir_mmc_path, FS_TYPE, MS_MGC_VAL | MS_NOSUID,
657 ("App2Sd Error : Read Write Mount failed [System Erro no is %d]\n",
659 ret = APP2EXT_ERROR_MOUNT;
663 case MOUNT_TYPE_RW_NOEXEC:
666 mount(dev, app_dir_mmc_path, FS_TYPE,
667 MS_MGC_VAL | MS_NOEXEC | MS_NOSUID, NULL)) < 0) {
669 ("App2Sd Error : RWX Mount failed [System Erro no is %d]\n",
671 ret = APP2EXT_ERROR_MOUNT;
675 case MOUNT_TYPE_RD_REMOUNT:
678 mount(dev, app_dir_mmc_path, FS_TYPE,
679 MS_MGC_VAL | MS_RDONLY | MS_REMOUNT | MS_NOSUID,
682 ("App2Sd Error : RWX Mount failed [System Erro no is %d]\n",
684 ret = APP2EXT_ERROR_MOUNT;
688 case MOUNT_TYPE_RW_REMOUNT:
691 mount(dev, app_dir_mmc_path, FS_TYPE,
692 MS_MGC_VAL | MS_REMOUNT | MS_NOSUID, NULL)) < 0) {
694 ("App2Sd Error : RWX Mount failed [System Erro no is %d]\n",
696 ret = APP2EXT_ERROR_MOUNT;
703 app2ext_print("App2Sd Error: Invalid mount type\n");
707 if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC || cmd == APP2SD_PRE_UPGRADE) {
708 ret = _app2sd_create_directory_entry(pkgid, dir_list);
713 int _app2sd_unmount_app_content(const char *pkgid)
715 int ret = APP2EXT_SUCCESS;
716 char app_dir_mmc_path[FILENAME_MAX] = { 0, };
718 snprintf(app_dir_mmc_path, FILENAME_MAX, "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid);
719 if ((ret = umount(app_dir_mmc_path)) < 0) {
720 char err_buf[1024] = {0,};
721 strerror_r(errno, err_buf, sizeof(err_buf));
722 app2ext_print("Unable to umount the dir %s\n", err_buf);
727 static int _app2sd_move_to_archive(const char *src_path, const char *arch_path)
729 int ret = APP2EXT_SUCCESS;
731 ret = _app2sd_copy_dir(src_path, arch_path);
732 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
733 char err_buf[1024] = {0,};
734 strerror_r(errno, err_buf, sizeof(err_buf));
735 app2ext_print("App2Sd Error : unable to copy from %s to %s .....err is %s\n",
736 src_path, arch_path, err_buf);
737 return APP2EXT_ERROR_MOVE;
740 ret = _app2sd_delete_directory((char *)src_path);
741 if (ret && ret != APP2EXT_ERROR_ACCESS_FILE) {
742 app2ext_print("App2Sd Error : unable to delete %s \n", src_path);
743 return APP2EXT_ERROR_DELETE_DIRECTORY;
749 int _app2sd_move_app_to_external(const char *pkgid, GList* dir_list)
751 int ret = APP2EXT_SUCCESS;
752 char app_path[FILENAME_MAX] = { 0, };
753 char path[FILENAME_MAX] = { 0, };
754 char app_mmc_path[FILENAME_MAX] = { 0, };
755 char app_archive_path[FILENAME_MAX] = { 0, };
756 char mmc_path[FILENAME_MAX] = { 0, };
757 unsigned long long total_size = 0;
759 int reqd_disk_size = 0;
760 char *device_node = NULL;
762 mode_t mode = DIR_PERMS;
763 int free_mmc_mem = 0;
766 app2ext_dir_details* dir_detail = NULL;
768 /* Check whether MMC is present or not */
769 ret = _app2sd_check_mmc_status();
772 ("App2Sd Error : MMC not preset OR Not ready %d\n",
774 return APP2EXT_ERROR_MMC_STATUS;
777 snprintf(mmc_path, FILENAME_MAX,
778 "%s%s", APP2SD_PATH, pkgid);
780 /* check whether application is in external memory or not */
781 fp = fopen(mmc_path, "r+");
784 ("Already %s entry is present in the SD Card, delete entry and go on without return\n",
787 app2sd_force_clean(pkgid);
790 snprintf(app_mmc_path, FILENAME_MAX,
791 "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid);
792 snprintf(app_archive_path, FILENAME_MAX,
793 "%s%s/.archive", APP_INSTALLATION_PATH, pkgid);
795 ret = mkdir(app_archive_path, mode);
797 if (errno != EEXIST) {
799 ("App2sd Error: Unable to create directory for archiving, error no is %d\n",
804 list = g_list_first(dir_list);
806 dir_detail = (app2ext_dir_details *)list->data;
807 if (dir_detail && dir_detail->name
808 && dir_detail->type == APP2EXT_DIR_RO) {
809 memset((void *)&app_path, '\0',
811 snprintf(app_path, FILENAME_MAX,
812 "%s%s/%s",APP_INSTALLATION_PATH,
816 _app2sd_calculate_dir_size
819 list = g_list_next(list);
822 reqd_size = ((total_size)/( 1024 * 1024)) + 2;
823 reqd_disk_size = reqd_size + ceil(reqd_size * 0.2);
825 /* Find avialable free memory in the MMC card */
827 _app2sd_get_available_free_memory
828 (MMC_PATH, &free_mmc_mem);
831 ("App2Sd Error : Unable to get available free memory in MMC %d\n",
833 return APP2EXT_ERROR_MMC_STATUS;
835 /* If avaialalbe free memory in MMC is less than required size + 5MB , return error */
836 if (reqd_disk_size > free_mmc_mem) {
838 ("App2Sd Error : Insufficient memory in MMC for application installation %d\n",
840 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY;
842 /* Create a loopback device */
844 _app2sd_create_loopback_device(pkgid, (reqd_disk_size+PKG_BUF_SIZE));
847 ("App2Sd Error : loopback node creation failed\n");
849 /* Perform Loopback encryption setup */
851 _app2sd_do_loopback_encryption_setup(pkgid);
854 ("App2Sd Error : losetup failed, device node is %s\n",
856 return APP2EXT_ERROR_DO_LOSETUP;
858 /* Check whether loopback device is associated with device node or not */
859 devi = _app2sd_find_associated_device_node(pkgid);
862 ("App2Sd Error : _app2sd_find_associated_device_node losetup failed\n");
863 return APP2EXT_ERROR_DO_LOSETUP;
868 /* Format the loopback file system */
869 ret = _app2sd_create_file_system(device_node);
872 ("App2Sd Error : create ext4 filesystem failed\n");
873 return APP2EXT_ERROR_CREATE_FS;
875 /********Archiving code begin***********/
876 list = g_list_first(dir_list);
878 dir_detail = (app2ext_dir_details *)list->data;
879 if (dir_detail && dir_detail->name
880 && dir_detail->type == APP2EXT_DIR_RO) {
881 snprintf(path, FILENAME_MAX,
882 "%s%s/%s",APP_INSTALLATION_PATH,
886 _app2sd_move_to_archive
890 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
892 ("App2Sd Error : unable to access %s\n",
896 ("App2Sd Error : unable to copy from %s to %s \n",
902 list = g_list_next(list);
904 /********Archiving code ends***********/
906 /* mount the loopback encrypted pseudo device on application installation path as with Read Write permission */
908 _app2sd_mount_app_content(pkgid, device_node,
909 MOUNT_TYPE_RW, dir_list,
910 APP2SD_MOVE_APP_TO_MMC);
914 /********restore Archive begin***********/
915 list = g_list_first(dir_list);
917 dir_detail = (app2ext_dir_details *)list->data;
918 if (dir_detail && dir_detail->name
919 && dir_detail->type == APP2EXT_DIR_RO) {
920 memset((void *)&path, '\0',
922 snprintf(path, FILENAME_MAX,
923 "%s%s/.archive/%s",APP_INSTALLATION_PATH,
931 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
932 app2ext_print("App2Sd Error : unable to access %s\n", path);
934 char err_buf[1024] = {0,};
935 strerror_r(errno, err_buf, sizeof(err_buf));
936 app2ext_print("App2Sd Error : unable to copy from %s to %s .....err is %s\n",
937 path, app_mmc_path, err_buf);
941 _app2sd_delete_directory
944 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
946 ("App2Sd Error : unable to access %s\n",
950 ("App2Sd Error : unable to delete %s \n",
953 APP2EXT_ERROR_DELETE_DIRECTORY;
957 list = g_list_next(list);
960 ret = _app2sd_delete_directory(app_archive_path);
963 ("App2Sd Error : unable to delete %s \n",
969 ret = _app2sd_apply_mmc_smack(pkgid, dir_list, pkgid);
972 app2ext_print("App2Sd Error : unable to apply app smack\n");
973 return APP2EXT_ERROR_MOVE;
976 /* Restore archive ends */
977 /* Re-mount the loopback encrypted pseudo device on application installation path as with Read Only permission */
978 ret = _app2sd_unmount_app_content(pkgid);
980 return APP2EXT_ERROR_REMOUNT;
983 _app2sd_remove_loopback_encryption_setup(pkgid);
986 ("App2Sd Error : unable to detach loopback setup for %s\n",
988 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
990 return APP2EXT_SUCCESS;
993 int _app2sd_move_app_to_internal(const char *pkgid, GList* dir_list)
995 int ret = APP2EXT_SUCCESS;
996 mode_t mode = DIR_PERMS;
997 char path[FILENAME_MAX] = { 0, };
998 char app_mmc_path[FILENAME_MAX] = { 0, };
999 char app_path[FILENAME_MAX] = { 0, };
1000 char mmc_path[FILENAME_MAX] = { 0, };
1001 char app_archive_path[FILENAME_MAX] = { 0, };
1002 char *device_node = NULL;
1005 app2ext_dir_details* dir_detail = NULL;
1007 int free_internal_mem = 0;
1008 struct statvfs buf = {0,};
1009 unsigned long long temp = 0;
1010 char err_buf[1024] = {0,};
1012 snprintf(app_mmc_path, FILENAME_MAX,
1013 "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid);
1014 snprintf(app_path, FILENAME_MAX, "%s%s/", APP_INSTALLATION_PATH,
1016 snprintf(app_archive_path, FILENAME_MAX,
1017 "%s%s/.archive", APP_INSTALLATION_PATH, pkgid);
1018 snprintf(mmc_path, FILENAME_MAX,
1019 "%s%s", APP2SD_PATH, pkgid);
1021 /* Check whether MMC is present or not */
1022 ret = _app2sd_check_mmc_status();
1025 ("App2Sd Error : MMC not preset OR Not ready %d\n",
1027 return APP2EXT_ERROR_MMC_STATUS;
1030 /* check whether application is in external memory or not */
1031 fp = fopen(mmc_path, "r+");
1034 ("Application %s is not installed on SD Card\n",
1036 return APP2EXT_ERROR_FILE_ABSENT;
1042 memset((void *)&buf, '\0', sizeof(struct statvfs));
1043 ret = statvfs(INTERNAL_STORAGE_PATH, &buf);
1045 temp = (buf.f_bsize * buf.f_bavail)/(1024*1024);
1046 free_internal_mem = (int)temp;
1048 app2ext_print("App2SD Error: Unable to get internal storage size\n");
1049 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY; /* TODO: new error no for internal? */
1052 /* check app entry is there in sd card or not. */
1053 snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH,
1055 app2ext_print("App2Sd Log : Checking path %s\n", app_path);
1056 fp = fopen(app_path, "r+");
1059 ("App2SD Error: App Entry is not present in SD Card\n");
1060 return APP2EXT_ERROR_INVALID_PACKAGE;
1063 /* Get installed app size*/
1064 temp = _app2sd_calculate_file_size(app_path);
1065 reqd_size = (int)((temp)/(1024 * 1024));
1066 app2ext_print("App2Sd Log : Reqd size is %d\n", reqd_size);
1068 if (reqd_size == 0) {
1070 ("App2SD Error: App Entry is not present in SD Card\n");
1071 return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE;
1074 app2ext_print("Reqd Size: %d MB, free internal mem %d MB\n", reqd_size, free_internal_mem);
1075 /* If avaialalbe free memory in internal storage is less than required size, return error */
1076 if (reqd_size > free_internal_mem) {
1078 ("App2Sd Error : Insufficient memory in internal storage for application installation %d\n",
1080 return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY; /* TODO: new error no for internal? */
1082 /* Get the associated device node for SD card applicationer */
1083 snprintf(app_path, FILENAME_MAX, "%s%s/", APP_INSTALLATION_PATH,
1087 _app2sd_find_associated_device_node(pkgid);
1088 if (NULL == device_node) {
1089 /* Do loopback setup */
1091 _app2sd_do_loopback_encryption_setup
1093 if (device_node == NULL) {
1095 ("App2Sd Error : loopback encryption setup failed\n");
1096 return APP2EXT_ERROR_DO_LOSETUP;
1100 _app2sd_mount_app_content(pkgid,
1104 APP2SD_MOVE_APP_TO_PHONE);
1107 ("App2Sd Error : Re-mount failed\n");
1108 return APP2EXT_ERROR_MOUNT_PATH;
1111 /* Do re-mounting */
1113 _app2sd_mount_app_content(pkgid,
1115 MOUNT_TYPE_RW_REMOUNT,
1117 APP2SD_MOVE_APP_TO_PHONE);
1120 ("App2Sd Error : Re-mount failed\n");
1121 return APP2EXT_ERROR_MOUNT_PATH;
1124 ret = mkdir(app_archive_path, mode);
1127 ("App2Sd Error : unable to create directory%s\n",
1132 list = g_list_first(dir_list);
1134 dir_detail = (app2ext_dir_details *)list->data;
1135 if (dir_detail && dir_detail->name
1136 && dir_detail->type == APP2EXT_DIR_RO) {
1137 /* Archiving code */
1138 memset((void *)&path, '\0',
1140 snprintf(path, FILENAME_MAX,
1141 "%s%s/.mmc/%s", APP_INSTALLATION_PATH,
1149 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1150 app2ext_print("App2Sd Error : unable to access %s\n", path);
1152 strerror_r(errno, err_buf, sizeof(err_buf));
1153 app2ext_print("App2Sd Error : unable to copy from %s to %s .....err is %s\n",
1154 path, app_archive_path, err_buf);
1158 /* Delete the symbolic link files [bin, lib, res]*/
1159 memset((void *)&path, '\0',
1161 snprintf(path, FILENAME_MAX,
1162 "%s%s/%s", APP_INSTALLATION_PATH,
1167 if (errno == ENOENT) {
1168 app2ext_print("App2Sd Error : Directory %s does not exist\n", path);
1170 app2ext_print("App2Sd Error : unable to remove the symbolic link file %s,"
1171 " it is already unlinked!!!\n", path);
1175 /* Copy content to destination */
1176 memset((void *)&path, '\0',
1178 snprintf(path, FILENAME_MAX,
1179 "%s%s/.archive/%s", APP_INSTALLATION_PATH,
1180 pkgid, dir_detail->name);
1181 ret = _app2sd_copy_dir(path, app_path);
1183 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1184 app2ext_print("App2Sd Error : unable to access %s\n", path);
1186 strerror_r(errno, err_buf, sizeof(err_buf));
1187 app2ext_print("App2Sd Error : unable to copy from %s to %s .....err is %s\n",
1188 path, app_path, err_buf);
1192 list = g_list_next(list);
1195 app2ext_print("App2Sd info : Copying file completed\n");
1196 ret = _app2sd_unmount_app_content(pkgid);
1199 ("App2Sd Error : unable to unmount SD directory for app %s\n",
1201 return APP2EXT_ERROR_UNMOUNT;
1204 _app2sd_remove_loopback_encryption_setup(pkgid);
1207 ("App2Sd Error : unable to detach loopback setup for %s\n",
1209 return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE;
1211 ret = _app2sd_delete_loopback_device(pkgid);
1214 ("App2Sd Error : unable to delete the loopback device for %s\n",
1216 return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1218 ret = _app2sd_delete_directory(app_mmc_path);
1221 ("App2Sd Error : unable to delete %s \n",
1224 ret = _app2sd_delete_directory(app_archive_path);
1227 ("App2Sd Error : unable to delete %s \n",
1233 ret = _app2sd_apply_app_smack(pkgid, dir_list, pkgid);
1236 app2ext_print("App2Sd Error : unable to apply app smack\n");
1237 return APP2EXT_ERROR_MOVE;
1240 return APP2EXT_SUCCESS;
1243 int _app2sd_move_app(const char *pkgid, app2ext_move_type move_cmd, GList* dir_list)
1245 int ret = APP2EXT_SUCCESS;
1247 /* Check whether MMC is present or not */
1248 ret = _app2sd_check_mmc_status();
1251 ("App2Sd Error : MMC not preset OR Not ready %d\n",
1253 return APP2EXT_ERROR_MMC_STATUS;
1257 case APP2EXT_MOVE_TO_EXT:
1259 ret = _app2sd_move_app_to_external(pkgid, dir_list);
1262 ("App2Sd Error : move app to external memory failed %d\n",
1268 case APP2EXT_MOVE_TO_PHONE:
1270 ret = _app2sd_move_app_to_internal(pkgid, dir_list);
1273 ("App2Sd Error : move app to internal memory failed %d\n",
1281 app2ext_print("App2Sd Error : invalid argument\n");
1282 return APP2EXT_ERROR_INVALID_ARGUMENTS;
1290 int _app2sd_copy_ro_content(const char *src, const char *dest, GList* dir_list)
1292 char path[FILENAME_MAX] = { 0, };
1293 int ret = APP2EXT_SUCCESS;
1295 app2ext_dir_details* dir_detail = NULL;
1297 list = g_list_first(dir_list);
1299 dir_detail = (app2ext_dir_details *)list->data;
1300 if (dir_detail && dir_detail->name
1301 && dir_detail->type == APP2EXT_DIR_RO) {
1302 memset((void *)&path, '\0',
1304 snprintf(path, FILENAME_MAX,
1312 if (ret == APP2EXT_ERROR_ACCESS_FILE) {
1314 ("App2Sd Error : unable to access %s\n",
1318 ("App2Sd Error : unable to copy from %s to %s .....errno is %d\n",
1327 list = g_list_next(list);
1330 return APP2EXT_SUCCESS;
1333 int _app2sd_duplicate_device(const char *pkgid, GList* dir_list, char *dev_node, int size)
1336 char temp_pkgid[FILENAME_MAX] = { 0, };
1339 char *result = NULL;
1341 /* Create a new loopback device */
1342 snprintf(temp_pkgid, FILENAME_MAX,
1344 ret = _app2sd_create_loopback_device(temp_pkgid, (size+PKG_BUF_SIZE));
1346 app2ext_print("App2Sd Error : Package already present\n");
1349 app2ext_print("App2Sd : _app2sd_create_loopback_device SUCCESS\n");
1350 /* Perform Loopback encryption setup */
1351 dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid, temp_pkgid);
1353 app2ext_print("App2Sd Error : losetup failed, device node is %s\n", dev_node);
1354 _app2sd_delete_loopback_device(pkgid);
1355 app2ext_print("App2Sd Error : create ext filesystem failed\n");
1356 return APP2EXT_ERROR_DO_LOSETUP;
1358 app2ext_print("App2Sd : _app2sd_do_loopback_duplicate_encryption_setup SUCCESS\n");
1359 /* Check whether loopback device is associated with device node or not */
1360 devi = _app2sd_find_associated_device_node(temp_pkgid);
1362 app2ext_print("App2Sd Error : finding associated device node failed\n");
1363 err_res = APP2EXT_ERROR_DO_LOSETUP;
1366 app2ext_print("App2Sd : _app2sd_find_associated_device_node SUCCESS\n");
1367 /* Format the loopback file system */
1368 ret = _app2sd_create_file_system(dev_node);
1370 app2ext_print("App2Sd Error : creating FS failed failed\n");
1371 err_res = APP2EXT_ERROR_CREATE_FS;
1374 app2ext_print("App2Sd : _app2sd_create_file_system SUCCESS\n");
1375 /* Do mounting for new dev*/
1377 _app2sd_mount_app_content(temp_pkgid, dev_node, MOUNT_TYPE_RW,
1378 dir_list, APP2SD_PRE_UPGRADE);
1380 app2ext_print("App2Sd Error : Re-mount failed\n");
1381 err_res = APP2EXT_ERROR_MOUNT_PATH;
1388 return APP2EXT_SUCCESS;
1392 result = _app2sd_detach_loop_device(dev_node);
1397 _app2sd_delete_loopback_device(pkgid);
1409 int _app2sd_update_loopback_device_size(const char *pkgid,
1410 int size, GList* dir_list)
1413 char *device_node = NULL;
1414 char *old_device_node = NULL;
1416 char app_mmc_path[FILENAME_MAX] = { 0, };
1417 char app_archive_path[FILENAME_MAX] = { 0, };
1418 char temp_pkgid[FILENAME_MAX] = { 0, };
1419 char app_path[FILENAME_MAX] = { 0, };
1421 snprintf(temp_pkgid, FILENAME_MAX,
1424 ret = _app2sd_duplicate_device(pkgid, dir_list, device_node, size);
1426 app2ext_print("App2Sd Error : Creating duplicate device failed\n");
1430 app2ext_print("App2Sd : _app2sd_mount_app_content SUCCESS\n");
1431 /* check app entry is there in sd card or not. */
1432 snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH,
1435 /* Get the associated device node for SD card applicatione */
1436 old_device_node = _app2sd_find_associated_device_node(pkgid);
1437 if (NULL == old_device_node) {
1438 /* Do loopback setup */
1439 old_device_node = _app2sd_do_loopback_encryption_setup(pkgid);
1440 if (old_device_node == NULL) {
1442 ("App2Sd Error : loopback encryption setup failed\n");
1443 err_res = APP2EXT_ERROR_DO_LOSETUP;
1448 _app2sd_mount_app_content(pkgid, old_device_node,
1449 MOUNT_TYPE_RW, dir_list,
1450 APP2SD_PRE_UPGRADE);
1452 app2ext_print("App2Sd Error : Re-mount failed\n");
1453 err_res = APP2EXT_ERROR_MOUNT_PATH;
1456 /* Do re-mounting */
1458 _app2sd_mount_app_content(pkgid, old_device_node,
1459 MOUNT_TYPE_RW_REMOUNT, dir_list,
1460 APP2SD_PRE_UPGRADE);
1462 app2ext_print("App2Sd Error : Re-mount failed\n");
1463 err_res = APP2EXT_ERROR_MOUNT_PATH;
1467 snprintf(app_mmc_path, FILENAME_MAX,
1468 "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid);
1469 snprintf(app_archive_path, FILENAME_MAX,
1470 "%s%s/.mmc", APP_INSTALLATION_PATH, temp_pkgid);
1472 ret = _app2sd_copy_ro_content(app_mmc_path, app_archive_path, dir_list);
1474 app2ext_print("App2Sd Error : copy ro content failed\n");
1478 ret = _app2sd_unmount_app_content(pkgid);
1481 ("App2SD Error: Unable to unmount the SD application\n");
1482 err_res = APP2EXT_ERROR_UNMOUNT;
1484 ret = _app2sd_remove_loopback_encryption_setup(pkgid);
1486 app2ext_print("App2SD Error: Unable to remove loopback setup\n");
1487 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1489 ret = _app2sd_unmount_app_content(temp_pkgid);
1492 ("App2SD Error: Unable to unmount the SD application\n");
1493 err_res = APP2EXT_ERROR_UNMOUNT;
1496 ret = _app2sd_remove_loopback_encryption_setup(temp_pkgid);
1498 app2ext_print("App2SD Error: Unable to remove loopback setup\n");
1499 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1502 snprintf(app_archive_path, FILENAME_MAX,
1503 "%s%s", APP2SD_PATH, temp_pkgid);
1504 ret = _app2sd_delete_directory(app_path);
1507 ("App2Sd Error : unable to delete %s \n",
1509 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1512 ret = _app2sd_rename_dir(app_archive_path, app_path);
1515 ("App2Sd Error : unable to rename %s \n",
1517 err_res = APP2EXT_ERROR_MOVE;
1520 snprintf(app_path, FILENAME_MAX,
1521 "%s%s", APP_INSTALLATION_PATH, temp_pkgid);
1522 ret = _app2sd_delete_directory(app_path);
1525 ("App2Sd Error : unable to delete %s \n",
1527 err_res = APP2EXT_ERROR_DELETE_DIRECTORY;
1530 return APP2EXT_SUCCESS;
1533 if (old_device_node) {
1534 free(old_device_node);
1535 old_device_node = NULL;
1538 ret = _app2sd_remove_loopback_encryption_setup(pkgid);
1540 app2ext_print("App2SD Error: Unable to remove loopback setup\n");
1541 err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE;
1546 void _app2sd_make_result_info_file(char *pkgid, int size)
1551 char buf[FILENAME_MAX] = {0};
1552 const char* app_info_label = "*";
1553 char info_file[FILENAME_MAX] = {'\0', };
1558 snprintf(info_file, FILENAME_MAX, "/tmp/%s", pkgid);
1559 app2ext_print("App2SD info : File path = %s\n", info_file);
1561 file = fopen(info_file, "w");
1563 app2ext_print("App2SD Error: Couldn't open the file %s \n", info_file);
1567 snprintf(buf, 128, "%d\n", size);
1568 fwrite(buf, 1, strlen(buf), file);
1575 if(lsetxattr(info_file, "security.SMACK64", app_info_label, strlen(app_info_label), 0)) {
1576 app2ext_print("App2SD Error: error(%d) in setting smack label",errno);
1578 ret = chmod(info_file, 0777);
1583 ret = chown(info_file, 5000, 5000);