Revert "Revert "Support legacy image for backward-compatibility"" 27/109527/1
authorHwankyu Jhun <h.jhun@samsung.com>
Tue, 10 Jan 2017 08:55:49 +0000 (17:55 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Tue, 10 Jan 2017 08:55:52 +0000 (17:55 +0900)
This reverts commit 7bd2ec8239a32021fbcfdbcef7dd5fb67a99da53.

Change-Id: I30bedd776b2044b318ac577fdbfaf8d32bd5d54b

15 files changed:
inc/app2ext_interface.h
packaging/app2sd.spec
plugin/app2sd/CMakeLists.txt
plugin/app2sd/common/inc/app2sd_utils.h
plugin/app2sd/lib/app2sd_client_interface.c
plugin/app2sd/lib/app2sd_client_interface.h
plugin/app2sd/server/app2sd_interface.c
plugin/app2sd/server/app2sd_interface.h
plugin/app2sd/server/app2sd_internals.c
plugin/app2sd/server/app2sd_internals.h
plugin/app2sd/server/app2sd_internals_registry.c
plugin/app2sd/server/app2sd_internals_utils.c
plugin/app2sd/server/app2sd_server.c
src/app2ext_interface.c
test/src/test_app2ext.c

index 28e099f..a12925a 100644 (file)
@@ -102,7 +102,8 @@ typedef enum app2sd_cmd_t {
        APP2SD_APP_LAUNCH,
        APP2SD_APP_TERMINATE,
        APP2SD_MOVE_APP_TO_MMC,
-       APP2SD_MOVE_APP_TO_PHONE
+       APP2SD_MOVE_APP_TO_PHONE,
+       APP2SD_MIGRATE_LEGACY
 } app2sd_cmd;
 
 /**
@@ -157,6 +158,7 @@ typedef enum app2ext_error_t {
        APP2EXT_ERROR_SAME_LOOPBACK_DEVICE_EXISTS,
        APP2EXT_ERROR_PKGMGR_ERROR,
        APP2EXT_ERROR_KILLAPP_ERROR,
+       APP2EXT_ERROR_NOENTRY,
 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
        APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE,
        APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE,
@@ -329,7 +331,49 @@ typedef int (*app2ext_client_usr_force_clean)(const char *pkgid, uid_t uid);
 typedef int (*app2ext_client_force_clean)(const char *pkgid);
 
 /**
- * This structure defines the app2ext interfaces. Plugins have to implement these functions
+ * @brief : This function type is for a function that is implemented by plugin
+ * and called before migration of legacy mount image.
+ *
+ * @param[in]   pkgid           application package name which is to be migrated
+ * @return      0 if success, error code(>0) if fail
+ */
+typedef int (*app2ext_client_usr_pre_migrate_legacy)(const char *pkgid,
+               uid_t uid);
+
+/**
+ * @brief : This function type is for a function that is implemented by plugin
+ * and called after migration of legacy mount image.
+ *
+ * @param[in]   pkgid           application package name which is to be migrated
+ * @return      0 if success, error code(>0) if fail
+ */
+typedef int (*app2ext_client_usr_post_migrate_legacy)(const char *pkgid,
+               uid_t uid);
+
+/**
+ * @brief : This function type is for a function that is implemented by plugin
+ * and called to migrate legacy mount image.
+ *
+ * @param[in]   pkgid           application package name which is to be migrated
+ * @return      0 if success, error code(>0) if fail
+ */
+typedef int (*app2ext_client_migrate_legacy_all)(void);
+
+/**
+ * @brief : This function type is for a function that is implemented by plugin
+ * and called to get the external image name.
+ *
+ * @param[in]   pkgid           application package name
+ * @param[in]   uid           target user id
+ * @return      the name of external image
+ * @remark     the name should be freed after the use.
+ */
+typedef char *(*app2ext_client_usr_getname_image)(const char *pkgid,
+               uid_t uid);
+
+/**
+ * This structure defines the app2ext interfaces.
+ * Plugins have to implement these functions
  */
 typedef struct app2ext_interface_t {
        /* for library function */
@@ -346,6 +390,7 @@ typedef struct app2ext_interface_t {
        app2ext_client_disable_full_pkg         client_disable_full_pkg;
        app2ext_client_pre_move                 client_pre_move;
        app2ext_client_post_move                client_post_move;
+       app2ext_client_migrate_legacy_all       client_migrate_legacy_all;
 
        app2ext_client_usr_pre_install          client_usr_pre_install;
        app2ext_client_usr_post_install         client_usr_post_install;
@@ -358,6 +403,9 @@ typedef struct app2ext_interface_t {
        app2ext_client_usr_disable              client_usr_disable;
        app2ext_client_usr_pre_move             client_usr_pre_move;
        app2ext_client_usr_post_move            client_usr_post_move;
+       app2ext_client_usr_getname_image        client_usr_getname_image;
+       app2ext_client_usr_pre_migrate_legacy   client_usr_pre_migrate_legacy;
+       app2ext_client_usr_post_migrate_legacy  client_usr_post_migrate_legacy;
 } app2ext_interface;
 
 /**
@@ -436,6 +484,21 @@ API int app2ext_usr_force_clean_pkg(const char *pkgid, uid_t uid);
 API int app2ext_enable_all_external_pkgs(void);
 API int app2ext_disable_all_external_pkgs(void);
 
+/**
+ * @brief : This API migrate all legacy entries which are located in external memory
+ * @return      error < 0 if fail to migrate legacy
+ */
+API int app2ext_migrate_legacy_all(void);
+
+/**
+ * @brief : This API get the external image name
+ * @param[in]   pkgid           application package name
+ * @param[in]   uid           target user id
+ * @return      the name of external image
+ * @remark     the name should be freed after the use.
+ */
+API char *app2ext_usr_getname_image(const char *pkgid, uid_t uid);
+
 #ifdef __cplusplus
 }
 #endif
index 088e5c6..f6cb960 100644 (file)
@@ -1,6 +1,6 @@
 Name:       app2sd
 Summary:    Application installation on external memory
-Version:    0.5.43
+Version:    0.5.44
 Release:    1
 Group:      Application Framework/Package Management
 License:    Apache-2.0
@@ -16,6 +16,7 @@ BuildRequires:  pkgconfig(gio-2.0)
 BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(aul)
 BuildRequires:  pkgconfig(storage)
+BuildRequires:  pkgconfig(pkgmgr)
 BuildRequires:  cmake
 
 %if "%{?profile}" == "common"
index 5d0138b..74d2b72 100644 (file)
@@ -1,5 +1,5 @@
 # Required packages
-pkg_check_modules(app2sd_pkgs REQUIRED dlog pkgmgr-info gio-2.0 glib-2.0 db-util libtzplatform-config aul storage)
+pkg_check_modules(app2sd_pkgs REQUIRED dlog pkgmgr-info gio-2.0 glib-2.0 db-util libtzplatform-config aul storage pkgmgr)
 pkg_check_modules(app2sd_libpkgs REQUIRED dlog pkgmgr-info gio-2.0 glib-2.0)
 
 # Compiler flags
index 7039f70..e2c4d5e 100644 (file)
@@ -51,6 +51,7 @@ extern "C" {
 #define APP2EXT_SUCCESS 0
 
 #define OWNER_ROOT 0
+#define APPFW_UID 301
 #define REGULAR_USER 5000
 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
 #define EXTIMG_DIR "app2sd"
index 5c66bd5..2f8437d 100644 (file)
@@ -537,14 +537,16 @@ int app2sd_client_usr_pre_move_installed_app(const char *pkgid, GList *dir_list,
        }
        ret = pkgmgrinfo_pkginfo_get_installed_storage(info_handle, &storage);
        if (ret < 0) {
-               _E("failed to get installed storage for pkg(%s) of uid(%d), ret(%d)",
-                       pkgid, uid, ret);
+               _E("failed to get installed storage for pkg(%s) " \
+                       "of uid(%d), ret(%d)", pkgid, uid, ret);
                pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
                return APP2EXT_ERROR_PKGMGR_ERROR;
        }
 
-       if ((move_type == APP2EXT_MOVE_TO_EXT && storage == PMINFO_EXTERNAL_STORAGE)
-               || (move_type == APP2EXT_MOVE_TO_PHONE && storage == PMINFO_INTERNAL_STORAGE)) {
+       if ((move_type == APP2EXT_MOVE_TO_EXT && storage ==
+                       PMINFO_EXTERNAL_STORAGE)
+               || (move_type == APP2EXT_MOVE_TO_PHONE &&
+                       storage == PMINFO_INTERNAL_STORAGE)) {
                        _E("PKG_EXISTS in [%d] STORAGE", storage);
                        pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
                        return APP2EXT_ERROR_PKG_EXISTS;
@@ -613,6 +615,54 @@ int app2sd_client_post_move_installed_app(const char *pkgid,
        return ret;
 }
 
+int app2sd_client_usr_pre_migrate_legacy(const char *pkgid, uid_t uid)
+{
+       int ret = 0;
+       GVariant *param = NULL;
+
+       /* validate the function parameter recieved */
+       if (pkgid == NULL) {
+               _E("invalid function arguments");
+               return APP2EXT_ERROR_INVALID_ARGUMENTS;
+       }
+
+       param = g_variant_new("(si)", pkgid, uid);
+       ret = __app2sd_call_server_method("PreMigrateLegacy", param);
+
+       return ret;
+}
+
+int app2sd_client_usr_post_migrate_legacy(const char *pkgid, uid_t uid)
+{
+       int ret = 0;
+       GVariant *param = NULL;
+
+       /* validate the function parameter recieved */
+       if (pkgid == NULL) {
+               _E("invalid function arguments");
+               return APP2EXT_ERROR_INVALID_ARGUMENTS;
+       }
+
+       param = g_variant_new("(si)", pkgid, uid);
+       ret = __app2sd_call_server_method("PostMigrateLegacy", param);
+
+       return ret;
+}
+
+int app2sd_client_migrate_legacy_all()
+{
+       int ret = 0;
+
+       ret = __app2sd_call_server_method("MigrateLegacyAll", NULL);
+
+       return ret;
+}
+
+char *app2sd_client_usr_getname_image(const char *pkgid, uid_t uid)
+{
+       return _app2sd_get_encoded_name(pkgid, uid);
+}
+
 void app2ext_on_load(app2ext_interface *interface)
 {
        /* Plug-in Binding.*/
@@ -629,6 +679,7 @@ void app2ext_on_load(app2ext_interface *interface)
        interface->client_disable_full_pkg = app2sd_client_disable_full_pkg;
        interface->client_pre_move = app2sd_client_pre_move_installed_app;
        interface->client_post_move = app2sd_client_post_move_installed_app;
+       interface->client_migrate_legacy_all = app2sd_client_migrate_legacy_all;
 
        interface->client_usr_pre_install = app2sd_client_usr_pre_app_install;
        interface->client_usr_post_install = app2sd_client_usr_post_app_install;
@@ -641,4 +692,7 @@ void app2ext_on_load(app2ext_interface *interface)
        interface->client_usr_disable = app2sd_client_usr_on_demand_setup_exit;
        interface->client_usr_pre_move = app2sd_client_usr_pre_move_installed_app;
        interface->client_usr_post_move = app2sd_client_usr_post_move_installed_app;
+       interface->client_usr_getname_image = app2sd_client_usr_getname_image;
+       interface->client_usr_pre_migrate_legacy = app2sd_client_usr_pre_migrate_legacy;
+       interface->client_usr_post_migrate_legacy = app2sd_client_usr_post_migrate_legacy;
 }
index 7470e46..62df3f8 100644 (file)
@@ -194,7 +194,7 @@ int app2sd_client_on_demand_setup_init(const char *pkgid);
  * @param[in] pkgid            application package id
  * @pre                        Package must be installed and enabled
  *                     and application must be running in SD card
- * @post       application is disabked in SD card.
+ * @post       application is disabled in SD card.
  * @return     0 if success,  error code(>0) if fail
  * @remark     None.
  */
@@ -205,6 +205,42 @@ int app2sd_client_usr_force_clean(const char *pkgid, uid_t uid);
 int app2sd_client_force_clean(const char *pkgid);
 
 /**
+ * @brief : This API does pre operation for the migration of legacy external
+ *     image for the compatability with tizen 3.0 platform.
+ * @param[in] pkgid            application package id
+ * @return     0 if success,  error code(>0) if fail
+ * @remark     None.
+ */
+int app2sd_client_usr_pre_migrate_legacy(const char *pkgid, uid_t uid);
+
+/**
+ * @brief : This API does post operation for the migration of legacy external
+ *     image for the compatability with tizen 3.0 platform.
+ * @param[in] pkgid            application package id
+ * @return     0 if success,  error code(>0) if fail
+ * @remark     None.
+ */
+int app2sd_client_usr_post_migrate_legacy(const char *pkgid, uid_t uid);
+
+/**
+ * @brief : This API migrate all the legacy mount image in sd card to be comapatible
+ *     with tizen 3.0 platform.
+ * @param[in] pkgid            application package id
+ * @return     0 if success,  error code(>0) if fail
+ * @remark     None.
+ */
+int app2sd_client_migrate_legacy_all(void);
+
+/**
+ * @brief : This API get the external image name.
+ * @param[in] pkgid            application package id
+ * @param[in] uid              target user id
+ * @return     the name of external image
+ * @remark     the name should be freed after the use.
+ */
+char *app2sd_client_usr_getname_image(const char *pkgid, uid_t uid);
+
+/**
  * @brief : This is the plug-in load function.
  *     The plugin has to bind its functions to function pointers of storage handle
  * @param[in/out] st_interface         Specifies the storage interface.
index 213a284..37a66da 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <pkgmgr-info.h>
+#include <package-manager.h>
 #include <aul.h>
 
 #include "app2sd_internals.h"
@@ -424,7 +425,8 @@ int app2sd_usr_on_demand_setup_init(const char *pkgid, uid_t uid)
 
        fp = fopen(loopback_device, "r+");
        if (fp == NULL) {
-               _E("app entry is not present in SD Card");
+               _E("app entry is not present in SD Card, (%s), errno(%d)",
+                       loopback_device, errno);
                return APP2EXT_ERROR_INVALID_PACKAGE;
        }
        fclose(fp);
@@ -1333,15 +1335,15 @@ int app2sd_enable_full_pkg(void)
                ret = _app2sd_get_info_from_db(loopback_device,
                        &pkgid, &uid);
                if (ret) {
-                       _E("failed to get info from db");
-                       break;;
+                       _W("failed to get info from db, continue");
+                       continue;
                }
                if (pkgid) {
                        _D("pkgid(%s), uid(%d)", pkgid, uid);
                        ret = app2sd_usr_on_demand_setup_init(pkgid, uid);
                        if (ret) {
                                _E("error(%d)", ret);
-                               break;
+                               continue;
                        }
                        free(pkgid);
                        pkgid = NULL;
@@ -1389,3 +1391,281 @@ int app2sd_disable_full_pkg(void)
        sync();
        return ret;
 }
+
+static int _app2sd_migrate_legacy_image(const char *pkgid, const char *passwd,
+               const char *mmc_path, uid_t uid)
+{
+       int ret = 0;
+       char *device_node = NULL;
+       char *encoded_id = NULL;
+       char new_image[FILENAME_MAX] = { 0, };
+       char legacy_image[FILENAME_MAX] = { 0, };
+       char application_path[FILENAME_MAX] = { 0, };
+       uid_t default_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+
+       if (_is_global(uid)) {
+               snprintf(application_path, sizeof(application_path), "%s/%s",
+                       tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
+       } else {
+               tzplatform_set_user(uid);
+               snprintf(application_path, sizeof(application_path), "%s/%s",
+                       tzplatform_getenv(TZ_USER_APP), pkgid);
+               tzplatform_reset_user();
+       }
+
+       /* make the information and insert to DB */
+       encoded_id = _app2sd_get_encoded_name(pkgid, uid);
+       if (encoded_id == NULL)
+               return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
+       snprintf(new_image, sizeof(new_image), "%s/%s",
+               mmc_path, encoded_id);
+       free(encoded_id);
+
+       snprintf(legacy_image, sizeof(legacy_image), "%s/%s",
+               mmc_path, pkgid);
+
+       ret = _app2sd_rename_dir(legacy_image, new_image);
+       if (ret) {
+               _E("unable to rename (%s)", legacy_image);
+               return APP2EXT_ERROR_ACCESS_FILE;
+       }
+
+       ret = pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
+               INSTALL_EXTERNAL, new_image, uid);
+       if (ret < 0) {
+               _E("fail to update installed location " \
+                       "to db[%s, %d] of uid(%d), ret(%d)",
+                       pkgid, INSTALL_EXTERNAL, uid, ret);
+               return APP2EXT_ERROR_PKGMGR_ERROR;
+       }
+
+       /* update app2sd db */
+       if (_is_global(uid)) {
+               ret = _app2sd_remove_info_from_db(pkgid, default_uid);
+               if (ret) {
+                       _E("cannot remove info from db");
+                       return APP2EXT_ERROR_SQLITE_REGISTRY;
+               }
+       }
+       ret = _app2sd_set_info_in_db(pkgid, passwd, new_image, uid);
+       if (ret) {
+               _E("unable to save info");
+               return APP2EXT_ERROR_SQLITE_REGISTRY;
+       }
+
+#ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
+       device_node =
+               _app2sd_find_associated_dmcrypt_device_node(pkgid, uid);
+       if (device_node) {
+               _E("device_node(%s_%d) already associated", pkgid, uid);
+               return APP2EXT_ERROR_ALREADY_MOUNTED;
+       }
+
+       ret = _app2sd_dmcrypt_open_device(pkgid, new_image, false,
+               uid, &device_node);
+       if (ret) {
+               _E("dmcrypt open device error(%d)", ret);
+               return APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE;
+       }
+#else
+       result = (char *)_app2sd_find_associated_device(new_image);
+       /* process the string */
+       if ((result != NULL) && strstr(result, "/dev") != NULL) {
+               _E("already associated");
+               free(result);
+               result = NULL;
+               return APP2EXT_ERROR_ALREADY_MOUNTED;
+       }
+
+       /* do loopback setup */
+       device_node = _app2sd_do_loopback_encryption_setup(pkgid,
+               new_image, uid);
+       if (device_node == NULL) {
+               _E("loopback encryption setup failed");
+               return APP2EXT_ERROR_DO_LOSETUP;
+       }
+#endif
+
+       /* do mounting */
+       ret = _app2sd_mount_app_content(application_path, pkgid,
+               device_node, MOUNT_TYPE_RW, NULL,
+               APP2SD_MIGRATE_LEGACY, uid);
+       if (ret) {
+               _E("mount failed");
+               if (device_node) {
+                       free(device_node);
+                       device_node = NULL;
+               }
+               return APP2EXT_ERROR_MOUNT_PATH;
+       }
+
+       if (device_node) {
+               free(device_node);
+               device_node = NULL;
+       }
+
+       sync();
+       return APP2EXT_SUCCESS;
+}
+
+int app2sd_pre_migrate_legacy(const char *pkgid, uid_t uid)
+{
+        int ret = APP2EXT_SUCCESS;
+        char *passwd = NULL;
+        char *sdpath = NULL;
+       char mmc_path[FILENAME_MAX] = { 0, };
+       char file_path[FILENAME_MAX] = { 0, };
+       uid_t default_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+
+       /* check whether MMC is present or not */
+       ret = _app2sd_check_mmc_status(&sdpath);
+       if (ret) {
+               _E("MMC not present OR Not ready (%d)", ret);
+               return APP2EXT_ERROR_MMC_STATUS;
+       }
+       snprintf(mmc_path, sizeof(mmc_path), "%s/%s", sdpath, EXTIMG_DIR);
+       free(sdpath);
+       snprintf(file_path, sizeof(file_path), "%s/%s", mmc_path, pkgid);
+
+       ret = _app2sd_initialize_db();
+       if (ret) {
+               _E("app2sd db initialize failed");
+               return APP2EXT_ERROR_SQLITE_REGISTRY;
+       }
+
+       /* In the upgrade script, the information
+        * of legacy image are filled with default user-id,
+        * pkgid(from old db), passwd(from old db) and
+        * empty filename in app2sd db. */
+       if (!_app2sd_get_filename_from_db(pkgid, default_uid)) {
+               passwd = _app2sd_get_password_from_db(pkgid, default_uid);
+               if (passwd) {
+                       ret = _app2sd_migrate_legacy_image(pkgid, passwd,
+                               mmc_path, uid);
+                       free(passwd);
+                       passwd = NULL;
+               } else {
+                       _E("invalid package info");
+                       return APP2EXT_ERROR_INVALID_PACKAGE;
+               }
+       } else {
+               _W("same pkg exists, remove legacy file (%s)", file_path);
+               ret = remove(file_path);
+               if (ret < 0)
+                       _E("failed to remove, errno(%d)", errno);
+               return APP2EXT_ERROR_PKG_EXISTS;
+       }
+
+       return ret;
+}
+
+int app2sd_post_migrate_legacy(const char *pkgid, uid_t uid)
+{
+        int ret = APP2EXT_SUCCESS;
+        char *sdpath = NULL;
+       char *encoded_id = NULL;
+       char mmc_path[FILENAME_MAX] = { 0, };
+       char application_path[FILENAME_MAX] = { 0, };
+       char loopback_device[FILENAME_MAX] = { 0, };
+
+       /* check whether MMC is present or not */
+       ret = _app2sd_check_mmc_status(&sdpath);
+       if (ret) {
+               _E("MMC not present OR Not ready (%d)", ret);
+               return APP2EXT_ERROR_MMC_STATUS;
+       }
+       snprintf(mmc_path, sizeof(mmc_path), "%s/%s",
+               sdpath, EXTIMG_DIR);
+       free(sdpath);
+
+       if (_is_global(uid)) {
+               snprintf(application_path, sizeof(application_path), "%s/%s",
+                       tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
+       } else {
+               tzplatform_set_user(uid);
+               snprintf(application_path, sizeof(application_path), "%s/%s",
+                       tzplatform_getenv(TZ_USER_APP), pkgid);
+               tzplatform_reset_user();
+       }
+
+       encoded_id = _app2sd_get_encoded_name(pkgid, uid);
+       if (encoded_id == NULL) {
+               return APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
+       }
+       snprintf(loopback_device, sizeof(loopback_device), "%s/%s",
+               mmc_path, encoded_id);
+       free(encoded_id);
+
+       ret = __app2sd_finalize_device_setup(pkgid, loopback_device,
+               application_path, uid);
+       if (ret) {
+               _E("failed to finalize device setup");
+               return ret;
+       }
+
+       return APP2EXT_SUCCESS;
+}
+
+/* this function is called when sdcard is inserted */
+int app2sd_migrate_legacy_all(void)
+{
+        int ret = APP2EXT_SUCCESS;
+        int rc = 0;
+       char buf[FILENAME_MAX] = { 0, };
+        char app2sd_path[FILENAME_MAX] = { 0, };
+        char loopback_device[FILENAME_MAX] = { 0, };
+        char *sdpath = NULL;
+        DIR *dir = NULL;
+        struct dirent entry;
+        struct dirent *result = NULL;
+       uid_t default_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+       pkgmgr_client *pc;
+
+       /* check whether MMC is present or not */
+       ret = _app2sd_check_mmc_status(&sdpath);
+       if (ret) {
+               _E("MMC not present OR Not ready (%d)", ret);
+               return APP2EXT_ERROR_MMC_STATUS;
+       }
+       snprintf(app2sd_path, sizeof(app2sd_path), "%s/%s",
+               sdpath, EXTIMG_DIR);
+       free(sdpath);
+
+       dir = opendir(app2sd_path);
+       if (!dir) {
+               strerror_r(errno, buf, sizeof(buf));
+               _E("failed to opendir (%s)", buf);
+               return APP2EXT_ERROR_OPEN_DIR;
+       }
+
+       pc = pkgmgr_client_new(PC_REQUEST);
+       if (pc == NULL) {
+               _E("failed to create pkgmgr client");
+               return APP2EXT_ERROR_PKGMGR_ERROR;
+       }
+
+       for (rc = readdir_r(dir, &entry, &result);
+               rc == 0 && result != NULL;
+               rc = readdir_r(dir, &entry, &result)) {
+               if (strcmp(entry.d_name, ".") == 0 ||
+                       strcmp(entry.d_name, "..") == 0)
+                       continue;
+               snprintf(loopback_device, sizeof(loopback_device), "%s/%s",
+                       app2sd_path, entry.d_name);
+               /* check losetup image */
+               if (_app2sd_check_is_luks_device(loopback_device) == 0) {
+                       /* call installer backend
+                         * to change access-rule and broadcast this update */
+                       ret = pkgmgr_client_usr_migrate_external_image(pc,
+                               entry.d_name, default_uid);
+                       if (ret < 0)
+                               _E("failed to request migration, ret(%d)", ret);
+               }
+       }
+
+       pkgmgr_client_free(pc);
+       closedir(dir);
+
+       return ret;
+}
+
index 0e2d11a..1e6d27f 100644 (file)
@@ -63,6 +63,12 @@ int app2sd_enable_full_pkg(void);
 
 int app2sd_disable_full_pkg(void);
 
+int app2sd_pre_migrate_legacy(const char *pkgid, uid_t uid);
+
+int app2sd_post_migrate_legacy(const char *pkgid, uid_t uid);
+
+int app2sd_migrate_legacy_all(void);
+
 #ifdef __cplusplus
 }
 #endif
index e3b712f..6863358 100644 (file)
@@ -453,8 +453,17 @@ int _app2sd_dmcrypt_open_device(const char *pkgid, const char *loopback_device,
                return APP2EXT_ERROR_SQLITE_REGISTRY;
        }
 
-       snprintf(dmcrypt_open_cmd, BUF_SIZE, "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen %s %s",
-               passwd, loopback_device, dev_name);
+       if (_app2sd_check_is_luks_device(loopback_device) == 0) {
+               _W("legacy image format!");
+               snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
+                       "/bin/echo '%s' | /sbin/cryptsetup " \
+                       "-M plain -c aes-cbc-plain -h plain open %s %s",
+                       passwd, loopback_device, dev_name);
+       } else {
+               snprintf(dmcrypt_open_cmd, sizeof(dmcrypt_open_cmd),
+                       "/bin/echo '%s' | /sbin/cryptsetup -q luksOpen %s %s",
+                       passwd, loopback_device, dev_name);
+       }
        free(passwd);
 
        ret = system(dmcrypt_open_cmd);
@@ -530,6 +539,7 @@ char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid)
                _D("device_node: (%s)", dev_node);
                return dev_node;
        }
+       _D("can not access dev_node(%s), errno(%d)", dev_node, errno);
 
        free(dev_node);
        dev_node = NULL;
index 0d63709..4c37e02 100644 (file)
@@ -163,6 +163,9 @@ int _app2sd_initialize_db();
 /* this function is used to get password from db */
 char *_app2sd_get_password_from_db(const char *pkgid, uid_t uid);
 
+/* this function is used to get filename from db */
+char *_app2sd_get_filename_from_db(const char *pkgid, uid_t uid);
+
 /* this function removes info from db */
 int _app2sd_remove_info_from_db(const char *pkgid, uid_t uid);
 
@@ -193,6 +196,8 @@ int _app2sd_dmcrypt_close_device(const char *pkgid, uid_t uid);
 
 /* this function find associated dmcrypt device node */
 char *_app2sd_find_associated_dmcrypt_device_node(const char *pkgid, uid_t uid);
+
+int _app2sd_check_is_luks_device(const char *device_path);
 #endif
 
 #endif
index 42ee967..52d4536 100644 (file)
 #include <dirent.h>
 #include <time.h>
 #include <db-util.h>
+#include <grp.h>
+#include <pwd.h>
 
 #include "app2sd_internals.h"
 
 #define MAX_QUERY_LEN 4096
 #define PASSWORD_LENGTH 64
+#define BUFSIZE 4096
+
 /*
 ########### Internal APIs ##################
  */
@@ -40,6 +44,68 @@ sqlite3 *app2sd_db;
        "(pkgid TEXT NOT NULL, password TEXT NOT NULL, " \
        "filename TEXT NOT NULL, uid INTEGER, PRIMARY KEY(pkgid, uid))"
 
+static int _app2sd_db_change_perm(const char *db_file)
+{
+       char buf[BUFSIZE];
+       char pwuid_buf[1024];
+       char journal_file[BUFSIZE];
+       int fd;
+       char *files[3];
+       int ret, i;
+       uid_t uid = APPFW_UID;
+       struct passwd userinfo, *result = NULL;
+       files[0] = (char *)db_file;
+       files[1] = journal_file;
+       files[2] = NULL;
+
+       if (db_file == NULL)
+               return -1;
+
+       if (getuid() != OWNER_ROOT) {
+               _E("not allowed user");
+               return -1;
+       }
+
+       snprintf(journal_file, sizeof(journal_file), "%s%s", db_file, "-journal");
+
+       ret = getpwuid_r(uid, &userinfo, pwuid_buf, sizeof(pwuid_buf), &result);
+       if (ret != 0 || result == NULL) {
+               _E("user(%d) doesn't exist", uid);
+               return -1;
+       }
+
+       for (i = 0; files[i]; i++) {
+               fd = open(files[i], O_RDONLY);
+               if (fd == -1) {
+                       if (strerror_r(errno, buf, sizeof(buf)))
+                               strncpy(buf, "", BUFSIZE - 1);
+                       _E("failed to open %s : %s", files[i], buf);
+                       return -1;
+               }
+
+               ret = fchown(fd, uid, userinfo.pw_gid);
+               if (ret == -1) {
+                       if (strerror_r(errno, buf, sizeof(buf)))
+                               strncpy(buf, "", BUFSIZE - 1);
+                       _E("failed to fchown %s %d.%d : %s", files[i], uid,
+                                       userinfo.pw_gid, buf);
+                       close(fd);
+                       return -1;
+               }
+
+               ret = fchmod(fd, 0644);
+               if (ret == -1) {
+                       if (strerror_r(errno, buf, sizeof(buf)))
+                               strncpy(buf, "", BUFSIZE - 1);
+                       _E("failed to fchmod %s : %s", files[i], buf);
+                       close(fd);
+                       return -1;
+               }
+               close(fd);
+       }
+       return 0;
+}
+
 int _app2sd_initialize_db()
 {
        char *error_message = NULL;
@@ -78,6 +144,11 @@ int _app2sd_initialize_db()
                return -1;
        }
 
+       if (_app2sd_db_change_perm(APP2SD_DB_FILE) < 0) {
+               _E("failed to change permissions");
+               return -1;
+       }
+
        return 0;
 }
 
@@ -285,7 +356,7 @@ char *_app2sd_get_password_from_db(const char *pkgid, uid_t uid)
        sqlite3_stmt *stmt = NULL;
        int ret = 0;
 
-       query = sqlite3_mprintf("select * from app2sd_info " \
+       query = sqlite3_mprintf("select password from app2sd_info " \
                "where pkgid=%Q and uid=%d", pkgid, uid);
        if (query == NULL) {
                _E("failed to make a query");
@@ -304,14 +375,12 @@ char *_app2sd_get_password_from_db(const char *pkgid, uid_t uid)
                _W("no records found");
                goto FINISH_OFF;
        }
-       passwd = malloc(PASSWORD_LENGTH + 1);
-       if (passwd == NULL) {
+
+       passwd = strdup((const char *)sqlite3_column_text(stmt, 0));
+       if (!passwd) {
                _E("memory allocation failed");
                goto FINISH_OFF;
        }
-
-       strncpy(passwd, (const char *)sqlite3_column_text(stmt, 1),
-               PASSWORD_LENGTH);
        if (strlen(passwd) == 0) {
                _E("data is empty");
                goto FINISH_OFF;
@@ -333,3 +402,57 @@ FINISH_OFF:
 
        return NULL;
 }
+
+char *_app2sd_get_filename_from_db(const char *pkgid, uid_t uid)
+{
+       char *query = NULL;
+       char *filename = NULL;
+       sqlite3_stmt *stmt = NULL;
+       int ret = 0;
+
+       query = sqlite3_mprintf("select filename from app2sd_info " \
+               "where pkgid=%Q and uid=%d", pkgid, uid);
+       if (query == NULL) {
+               _E("failed to make a query");
+               return NULL;
+       }
+
+       ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
+       if (ret != SQLITE_OK) {
+               _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
+               sqlite3_free(query);
+               return NULL;
+       }
+
+       ret = sqlite3_step(stmt);
+       if (ret != SQLITE_ROW || ret == SQLITE_DONE) {
+               _W("no records found");
+               goto FINISH_OFF;
+       }
+
+       filename = strdup((const char *)sqlite3_column_text(stmt, 0));
+       if (!filename) {
+               _E("memory allocation failed");
+               goto FINISH_OFF;
+       }
+       if (strlen(filename) == 0) {
+               _E("data is empty");
+               goto FINISH_OFF;
+       }
+       if (SQLITE_OK != sqlite3_finalize(stmt)) {
+               _E("error : sqlite3_finalize");
+               goto FINISH_OFF;
+       }
+       sqlite3_free(query);
+
+       return filename;
+
+FINISH_OFF:
+       if (filename)
+               free(filename);
+
+       sqlite3_finalize(stmt);
+       sqlite3_free(query);
+
+       return NULL;
+}
index 1640af3..0f05306 100644 (file)
@@ -203,7 +203,7 @@ int _app2sd_copy_dir(const char *src, const char *dest)
                        return ret;
                } else {
                        _E("failed to open src(%s) dir, errno(%d)", errno);
-                       return APP2EXT_ERROR_MOVE;
+                       return APP2EXT_ERROR_ACCESS_FILE;
                }
        }
 
@@ -213,17 +213,17 @@ int _app2sd_copy_dir(const char *src, const char *dest)
        } else {
                if (errno == ENOENT) {
                        _E("dest(%s) not exist, failed!", dest);
-                       return APP2EXT_ERROR_MOVE;
+                       return APP2EXT_ERROR_ACCESS_FILE;
                } else {
                        _E("failed to open dest(%s) dir, errno(%d)", errno);
-                       return APP2EXT_ERROR_MOVE;
+                       return APP2EXT_ERROR_ACCESS_FILE;
                }
        }
 
        ret = _xsystem(argv_bin);
        if (ret) {
                _E("failed to copy dir, errno(%d)", errno);
-               return APP2EXT_ERROR_MOVE;
+               return APP2EXT_ERROR_ACCESS_FILE;
        }
        return ret;
 }
@@ -235,7 +235,7 @@ int _app2sd_rename_dir(const char *old_name, const char *new_name)
        ret = _xsystem(argv_bin);
        if (ret) {
                _E("mv/rename fail");
-               return APP2EXT_ERROR_MOVE;
+               return APP2EXT_ERROR_ACCESS_FILE;
        }
        return ret;
 }
@@ -617,3 +617,21 @@ char *_app2sd_generate_password(const char *pkgid)
 
        return ret_result;
 }
+
+#ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
+int _app2sd_check_is_luks_device(const char *device_path)
+{
+       int ret = 0;
+       int result = 1; /* default: luks format */
+       const char *argv_bin[] = { "/sbin/cryptsetup", "isLuks", device_path };
+       ret = _xsystem(argv_bin);
+       if (ret < 0)
+               _E("there was errot to check isLuks");
+
+       if (ret == 1) /* legacy format */
+               result = 0;
+
+       _D("ret(%d), result(%d)", ret, result);
+       return result;
+}
+#endif
index 9cd82c2..3be7117 100644 (file)
@@ -199,6 +199,19 @@ static const gchar introspection_xml[] =
 "              <method name='DisableFullPkg'>"
 "                      <arg type='i' name='result' direction='out'/>"
 "              </method>"
+"              <method name='PreMigrateLegacy'>"
+"                      <arg type='s' name='pkgid' direction='in'/>"
+"                      <arg type='i' name='uid' direction='in'/>"
+"                      <arg type='i' name='result' direction='out'/>"
+"              </method>"
+"              <method name='PostMigrateLegacy'>"
+"                      <arg type='s' name='pkgid' direction='in'/>"
+"                      <arg type='i' name='uid' direction='in'/>"
+"                      <arg type='i' name='result' direction='out'/>"
+"              </method>"
+"              <method name='MigrateLegacyAll'>"
+"                      <arg type='i' name='result' direction='out'/>"
+"              </method>"
 "      </interface>"
 "</node>";
 
@@ -223,10 +236,8 @@ static void _app2sd_server_return_method_error(GDBusMethodInvocation *invocation
 static int _app2sd_server_generate_directory_list(GVariantIter *iter, GList **list)
 {
        int result = APP2EXT_SUCCESS;
-       GVariantIter *iter;
        gchar *str = NULL;
        int type;
-       GList *list = NULL;
 
        app2ext_dir_details *dir_detail = NULL;
        while (g_variant_iter_loop(iter, "(si)", &str, &type)) {
@@ -250,7 +261,7 @@ static int _app2sd_server_generate_directory_list(GVariantIter *iter, GList **li
                        }
 
                        dir_detail->type = type;
-                       list = g_list_append(list, dir_detail);
+                       *list = g_list_append(*list, dir_detail);
                }
        }
 
@@ -685,6 +696,97 @@ static void _app2sd_server_disable_full_pkg(GDBusConnection *connection, const g
        g_dbus_method_invocation_return_value(invocation, param);
 }
 
+static void _app2sd_server_pre_migrate_legacy(GDBusConnection *connection,
+       const gchar *sender, GVariant *parameters,
+       GDBusMethodInvocation *invocation, uid_t sender_uid)
+{
+       GVariant *param = NULL;
+       int result = APP2EXT_SUCCESS;
+       char *pkgid = NULL;
+       uid_t target_uid = -1;
+       int ret = 0;
+
+       g_variant_get(parameters, "(&si)", &pkgid, &target_uid);
+
+       _D("pkgid(%s), target_uid(%d), sender_uid(%d)",
+               pkgid, target_uid, sender_uid);
+
+       if (!_app2sd_server_check_permission(sender_uid, sender_uid)) {
+               _E("Not permitted user!");
+               _app2sd_server_return_method_error(invocation,
+                       APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
+               return;
+       }
+
+       ret = app2sd_pre_migrate_legacy(pkgid, target_uid);
+       if (ret) {
+               _E("error(%d)", ret);
+               result = ret;
+       }
+
+       param = g_variant_new("(i)", result);
+       g_dbus_method_invocation_return_value(invocation, param);
+}
+
+static void _app2sd_server_post_migrate_legacy(GDBusConnection *connection,
+       const gchar *sender, GVariant *parameters,
+       GDBusMethodInvocation *invocation, uid_t sender_uid)
+{
+       GVariant *param = NULL;
+       int result = APP2EXT_SUCCESS;
+       char *pkgid = NULL;
+       uid_t target_uid = -1;
+       int ret = 0;
+
+       g_variant_get(parameters, "(&si)", &pkgid, &target_uid);
+
+       _D("pkgid(%s), target_uid(%d), sender_uid(%d)",
+               pkgid, target_uid, sender_uid);
+
+       if (!_app2sd_server_check_permission(sender_uid, sender_uid)) {
+               _E("Not permitted user!");
+               _app2sd_server_return_method_error(invocation,
+                       APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
+               return;
+       }
+
+       ret = app2sd_post_migrate_legacy(pkgid, target_uid);
+       if (ret) {
+               _E("error(%d)", ret);
+               result = ret;
+       }
+
+       param = g_variant_new("(i)", result);
+       g_dbus_method_invocation_return_value(invocation, param);
+}
+
+static void _app2sd_server_migrate_legacy_all(GDBusConnection *connection,
+       const gchar *sender, GVariant *parameters,
+       GDBusMethodInvocation *invocation, uid_t sender_uid)
+{
+       GVariant *param = NULL;
+       int result = APP2EXT_SUCCESS;
+       int ret = 0;
+
+       _D("sender_uid(%d)", sender_uid);
+
+       if (!_app2sd_server_check_permission(sender_uid, sender_uid)) {
+               _E("Not permitted user!");
+               _app2sd_server_return_method_error(invocation,
+                       APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
+               return;
+       }
+
+       ret = app2sd_migrate_legacy_all();
+       if (ret) {
+               _E("error(%d)", ret);
+               result = ret;
+       }
+
+       param = g_variant_new("(i)", result);
+       g_dbus_method_invocation_return_value(invocation, param);
+}
+
 static void handle_method_call(GDBusConnection *connection,
        const gchar *sender, const gchar *object_path,
        const gchar *interface_name, const gchar *method_name,
@@ -736,6 +838,15 @@ static void handle_method_call(GDBusConnection *connection,
        } else if (g_strcmp0(method_name, "DisableFullPkg") == 0) {
                _app2sd_server_disable_full_pkg(connection, sender,
                        parameters, invocation, sender_uid);
+       } else if (g_strcmp0(method_name, "PreMigrateLegacy") == 0) {
+               _app2sd_server_pre_migrate_legacy(connection, sender,
+                       parameters, invocation, sender_uid);
+       } else if (g_strcmp0(method_name, "PostMigrateLegacy") == 0) {
+               _app2sd_server_post_migrate_legacy(connection, sender,
+                       parameters, invocation, sender_uid);
+       } else if (g_strcmp0(method_name, "MigrateLegacyAll") == 0) {
+               _app2sd_server_migrate_legacy_all(connection, sender,
+                       parameters, invocation, sender_uid);
        }
 
        if (source_id)
index 5ec1602..07b70c2 100644 (file)
@@ -243,3 +243,42 @@ int app2ext_force_clean_pkg(const char *pkgid)
 
        return ret;
 }
+
+int app2ext_migrate_legacy_all(void)
+{
+       app2ext_handle *handle = NULL;
+
+       handle = app2ext_init(APP2EXT_SD_CARD);
+       if (handle == NULL) {
+               _E("app2ext init failed");
+               return -1;
+       }
+
+       handle->interface.client_migrate_legacy_all();
+       app2ext_deinit(handle);
+
+       return 0;
+}
+
+char *app2ext_usr_getname_image(const char *pkgid, uid_t uid)
+{
+       app2ext_handle *handle = NULL;
+       char *image_name = NULL;
+
+       /* validate the function parameter received */
+       if (pkgid == NULL) {
+               _E("invalid func parameters");
+               return NULL;
+       }
+
+       handle = app2ext_init(APP2EXT_SD_CARD);
+       if (handle == NULL) {
+               _E("app2ext init failed");
+               return NULL;
+       }
+
+       image_name = handle->interface.client_usr_getname_image(pkgid, uid);
+       app2ext_deinit(handle);
+
+       return image_name;
+}
index 69403f5..e07e186 100644 (file)
@@ -97,6 +97,7 @@ char error_list[COUNT_OF_ERROR_LIST][100] = {
        "APP2EXT_ERROR_OPERATION_NOT_PERMITTED",
        "APP2EXT_ERROR_SAME_LOOPBACK_DEVICE_EXISTS",
        "APP2EXT_ERROR_PKGMGR_ERROR",
+       "APP2EXT_ERROR_NOENTRY",
 #ifdef TIZEN_FEATURE_APP2SD_DMCRYPT_ENCRYPTION
        "APP2EXT_ERROR_SETUP_DMCRYPT_DEVICE",
        "APP2EXT_ERROR_OPEN_DMCRYPT_DEVICE",
@@ -110,37 +111,43 @@ static void usage(void)
 {
        printf("\n");
        printf("*************************************************\n");
-       printf("app2sd test usage:\n");
-       printf("pre-condition: /tmp/org.example.basicuiapplication-1.0.0-arm.tpk\n");
+       printf("App2sd test usage:\n");
+       printf("Pre-condition: /tmp/org.example.basicuiapplication-1.0.0-arm.tpk\n");
+       printf("All tests assume the target uid as default user.\n");
        printf("\n");
        printf("<INSTALL>\n");
-       printf("1.(at target_user)$test_app2ext --pre-install\n");
-       printf("2.(at target_user)$pkgcmd -it tpk {pkg-path}\n");
-       printf("3.(at target_user)$test_app2ext --post-install\n");
+       printf("1.#test_app2ext --pre-install\n");
+       printf("2.#pkgcmd -it tpk {pkg-path}\n");
+       printf("3.#test_app2ext --post-install\n");
        printf("------------------------------------------------\n");
        printf("\n");
        printf("<UPGRADE>\n");
-       printf("1.(at target_user)$test_app2ext --pre-upgrade\n");
-       printf("2.(at target_user)$pkgcmd -it tpk {pkg-path}\n");
-       printf("3.(at target_user)$test_app2ext --post-upgrade\n");
+       printf("1.#test_app2ext --pre-upgrade\n");
+       printf("2.#pkgcmd -it tpk {pkg-path}\n");
+       printf("3.#test_app2ext --post-upgrade\n");
        printf("------------------------------------------------\n");
        printf("\n");
        printf("<INSTALL>\n");
-       printf("1.(at target_user)$test_app2ext --pre-uninstall\n");
-       printf("2.(at target_user)$pkgcmd -un {pkg-id}\n");
-       printf("3.(at target_user)$test_app2ext --post-uninstall\n");
+       printf("1.#test_app2ext --pre-uninstall\n");
+       printf("2.#pkgcmd -un {pkg-id}\n");
+       printf("3.#test_app2ext --post-uninstall\n");
        printf("------------------------------------------------\n");
        printf("\n");
        printf("<MOVE PKG TEST>\n");
-       printf("(at target_user)$test_app2ext --move-to-ext\n");
-       printf("(at target_user)$test_app2ext --move-to-int\n");
+       printf("#test_app2ext --move-to-ext\n");
+       printf("#test_app2ext --move-to-int\n");
        printf("------------------------------------------------\n");
        printf("\n");
        printf("<ENABLE(mount)/DISABLE(umount) TEST W/ Installed PKG>\n");
-       printf("(at target_user)$test_app2ext --enable\n");
-       printf("(at target_user)$test_app2ext --disable\n");
-       printf("(at target_user)$test_app2ext --enable-full\n");
-       printf("(at target_user)$test_app2ext --disable-full\n");
+       printf("#test_app2ext --enable\n");
+       printf("#test_app2ext --disable\n");
+       printf("#test_app2ext --enable-full\n");
+       printf("#test_app2ext --disable-full\n");
+       printf("------------------------------------------------\n");
+       printf("\n");
+       printf("<MIGRATION TRIGGER TEST>\n");
+       printf("Pre-condition: install test package and copy legacy image to app2sd.\n");
+       printf("#test_app2ext --migrate-all\n");
        printf("------------------------------------------------\n");
        printf("**************************************************\n");
        printf("\n");
@@ -158,7 +165,8 @@ static void usage(void)
 #define OPTVAL_DISABLE_APP             1009
 #define OPTVAL_ENABLE_FULL             1010
 #define OPTVAL_DISABLE_FULL            1011
-#define OPTVAL_USAGE                   1012
+#define OPTVAL_MIGRATE_ALL             1012
+#define OPTVAL_USAGE                   1013
 
 /* Supported options */
 const struct option long_opts[] = {
@@ -174,6 +182,7 @@ const struct option long_opts[] = {
        { "disable", 0, NULL, OPTVAL_DISABLE_APP },
        { "enable-full", 0, NULL, OPTVAL_ENABLE_FULL },
        { "disable-full", 0, NULL, OPTVAL_DISABLE_FULL },
+       { "migrate-all", 0, NULL, OPTVAL_MIGRATE_ALL },
        { "help", 0, NULL, OPTVAL_USAGE },
        { "usage", 0, NULL, OPTVAL_USAGE },
        { 0, 0, 0, 0 }  /* sentinel */
@@ -385,6 +394,16 @@ static int fullpkg_disable()
        return ret;
 }
 
+static int migrate_all()
+{
+       int ret = -1;
+
+       ret = handle->interface.client_migrate_legacy_all();
+       print_error_code(__func__, ret);
+
+       return ret;
+}
+
 static int pre_app_uninstall()
 {
        int ret = -1;
@@ -512,13 +531,9 @@ int main(int argc, char **argv)
        uid_t uid = getuid();
 
        /* check user */
-       if (uid == GLOBAL_USER) {
-               printf("test for global app\n");
-       } else if (uid == OWNER_ROOT) {
-               printf("for root user, a test isn't supproted yet\n");
+       if (uid != OWNER_ROOT) {
+               printf("only root user allowed\n");
                return 0;
-       } else {
-               printf("test for user(%d) app\n", uid);
        }
 
        /* check sdcard info */
@@ -589,6 +604,9 @@ int main(int argc, char **argv)
                case OPTVAL_DISABLE_FULL:
                        fullpkg_disable();
                        break;
+               case OPTVAL_MIGRATE_ALL:
+                       migrate_all();
+                       break;
                case OPTVAL_USAGE:
                default:
                        usage();