Fix static analysis issue
[platform/core/appfw/app-installers.git] / src / common / shared_dirs.cc
index 8989802..ba17ea7 100644 (file)
@@ -34,9 +34,9 @@
 #include <vector>
 #include <tuple>
 
-#include "common/paths.h"
+#include "common/utils/paths.h"
 #include "common/security_registration.h"
-#include "common/pkgmgr_query.h"
+#include "common/utils/pkgmgr_query.h"
 #include "common/utils/base64.h"
 #include "common/utils/file_util.h"
 #include "common/utils/user_util.h"
@@ -51,6 +51,8 @@ namespace {
 
 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
 const utils::VersionNumber ver30("3.0");
+const char kDisableLegacySharedDataDirSupport[] =
+    "/usr/share/app-installers/disable_legacy_shareddata_support";
 
 const std::vector<const char*> kEntries = {
   {"shared"},
@@ -63,87 +65,72 @@ const std::vector<std::string> kReadOnlyEntries = {
   {"res"},
   {"shared/res"},
 };
+const std::vector<std::string> kSharedDataEntries = {
+  {".shared"},
+  {".shared_tmp"},
+};
 
 const char kSharedResDir[] = "shared/res";
 const char kSharedCacheDir[] = "shared/cache";
 const char kSharedDataDir[] = "shared/data";
+const char kShared[] = "shared";
+const char kData[] = "data";
+const char kCache[] = "cache";
+const char kSharedDir[] = ".shared";
+const char kSharedTmpDir[] = ".shared_tmp";
 const char kSharedTrustedDir[] = "shared/trusted";
 const char kSkelAppDir[] = "skel/apps_rw";
 const char kExternalStoragePrivilege[] =
     "http://tizen.org/privilege/externalstorage.appdata";
 const char kSystemShareGroupName[] = "system_share";
+const char kSubssesionDir[] = "subsession";
+// the input path should be root directory of package.
+// for example: "../apps_rw/pkgid" or "../.shared/pkgid"
+bool SetPackageDirectoryOwnerAndPermissions(const bf::path& path, uid_t uid) {
+  boost::optional<gid_t> gid = ci::GetGidByUid(uid);
+  if (!gid)
+    return false;
 
-bool SetDirectoryOwnerAndPermissions(const bf::path& subpath, uid_t uid,
-                                     gid_t gid) {
-  bf::perms perms = bf::owner_read |
-                    bf::owner_write |
-                    bf::group_read;
-  // symlink will be skipped
-  if (bf::is_symlink(symlink_status(subpath)))
-    return true;
+  bf::perms perms755 = bf::all_all ^ bf::group_write ^ bf::others_write;
+  bf::perms perms644 =
+      bf::owner_read | bf::owner_write | bf::group_read | bf::others_read;
+  bf::perms perms_setgid = perms755 | bf::set_gid_on_exe;
+  boost::optional<gid_t> system_share =
+    ci::GetGidByGroupName(kSystemShareGroupName);
+  // root path
+  if (!ci::SetDirOwnershipAndPermissions(path, perms755, uid, *gid))
+    return false;
 
-  // non directory will be skipped
-  bool result = true;
-  if (bf::is_directory(subpath)) {
-    perms |= bf::owner_exe | bf::group_exe | bf::others_read | bf::others_exe;
-    if (subpath.filename() == "data" || subpath.filename() == "cache") {
-      perms |= bf::group_write | bf::set_gid_on_exe;
-      boost::optional<gid_t> system_share =
-          ci::GetGidByGroupName(kSystemShareGroupName);
-      if (!system_share)
+  for (bf::recursive_directory_iterator iter(path);
+      iter != bf::recursive_directory_iterator(); ++iter) {
+    if (bf::is_symlink(symlink_status(iter->path()))) {
+      // skip symlink path
+      continue;
+    } else if (bf::is_directory(iter->path()) && iter.level() == 0 &&
+        (iter->path().filename() == ".mmc" ||
+            iter->path().filename() == ".pkg" ||
+            iter->path().filename() == "tep")) {
+      // skip path which is related to mount or directory installer creates
+      continue;
+    } else if (bf::is_directory(iter->path())) {
+      bool is_rw = false;
+      if (iter.level() == 0 &&
+              (iter->path().filename() == kData ||
+               iter->path().filename() == kCache))
+        is_rw = true;
+      if (!ci::SetDirOwnershipAndPermissions(
+              iter->path(), is_rw ? perms_setgid : perms755, uid,
+              is_rw ? *system_share : *gid))
         return false;
-      gid = *system_share;
-    }
-    result = common_installer::SetDirOwnershipAndPermissions(subpath, perms,
-                                                             uid, gid);
-  }
-
-  return result;
-}
-
-bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
-                       uid_t uid, gid_t gid, const bool set_permissions,
-                       const std::vector<const char*>
-                       additional_dirs = std::vector<const char*>()) {
-  bf::path base_dir = app_dir / pkgid;
-  if (bf::exists(base_dir)) {
-    LOG(DEBUG) << "Directory for user already exist: " << base_dir;
-    return true;
-  } else {
-    bs::error_code error;
-    bf::create_directories(base_dir, error);
-    if (error) {
-      LOG(ERROR) << "Failed to create directory: " << base_dir;
-      return false;
-    }
-  }
-
-  bs::error_code error;
-  std::vector<const char*> dirs(kEntries);
-  dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
-  // always trusted
-  dirs.push_back(kSharedTrustedDir);
-  for (auto& entry : dirs) {
-    bf::path subpath = base_dir / entry;
-    bf::create_directories(subpath, error);
-    if (error) {
-      LOG(ERROR) << "Failed to create directory: " << subpath;
-      return false;
-    }
-
-    if (set_permissions) {
-      if (!SetDirectoryOwnerAndPermissions(subpath, uid, gid))
+    } else {
+      bool is_bin = false;
+      if (iter.level() == 1 && iter->path().parent_path().filename() == "bin")
+        is_bin = true;
+      if (!ci::SetDirOwnershipAndPermissions(
+              iter->path(), is_bin ? perms755 : perms644, uid, *gid))
         return false;
-
-      // for content
-      for (bf::recursive_directory_iterator iter(subpath);
-           iter != bf::recursive_directory_iterator(); ++iter) {
-        if (!SetDirectoryOwnerAndPermissions(iter->path(), uid, gid))
-          return false;
-      }
     }
   }
-
   return true;
 }
 
@@ -157,38 +144,51 @@ bf::path GetDirectoryPathForStorage(uid_t user, std::string apps_prefix) {
   return apps_rw;
 }
 
-bool CreateUserDirectories(uid_t user, const std::string& pkgid,
-    const std::string& apps_prefix, const bool set_permissions) {
-  boost::optional<gid_t> gid = ci::GetGidByUid(user);
-  if (!gid)
+bool DeleteSharedDataDirectories(const bf::path& path,
+                                 const std::string& pkgid) {
+  if (!ci::RemoveAll(path / pkgid / kSharedDataDir))
     return false;
 
-  std::string group_name = ci::GetGroupNameByGid(*gid);
-  if (group_name != tzplatform_getenv(TZ_SYS_USER_GROUP))
-    return false;
+  std::vector<std::string> shared_dirs(kSharedDataEntries);
+  for (const auto& entry : shared_dirs) {
+    if (!ci::RemoveAll(path / entry / pkgid))
+      return false;
+  }
 
-  LOG(DEBUG) << "Creating directories for uid: " << user << ", gid: "
-             << *gid;
+  return true;
+}
 
-  bf::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
-  if (apps_rw.empty()) {
-    LOG(DEBUG) << "Directory not exists: " << apps_rw;
+bool CreateSharedDataDirectories(const bf::path& path,
+                                 const std::string& pkgid) {
+  if (!ci::CreateDir(path / kSharedDir / pkgid / kData) ||
+      !ci::CreateDir(path / kSharedTmpDir / pkgid) ||
+      !ci::CreateDir(path / pkgid / kShared))
     return false;
-  }
 
-  if (!CreateDirectories(apps_rw, pkgid,
-     user, *gid, set_permissions)) {
+  bf::current_path(path / pkgid / kShared);
+  if (bf::exists(path / pkgid / kShared / kData))
+    return true;
+  bf::path relative_path = ci::RelativePath(path / kSharedDir / pkgid / kData,
+                                            bf::current_path() / kData);
+  bs::error_code error;
+  bf::create_symlink(relative_path, kData, error);
+  if (error) {
+    LOG(ERROR) << "Failed to create symlink : " << error.message();
     return false;
   }
+
   return true;
 }
 
 bool DeleteDirectories(const bf::path& app_dir, const std::string& pkgid) {
   bf::path base_dir = app_dir / pkgid;
-  return ci::RemoveAll(base_dir);
+  if (!ci::RemoveAll(base_dir))
+    return false;
+  if (!DeleteSharedDataDirectories(app_dir, pkgid))
+    return false;
+  return true;
 }
 
-
 bool CreateSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
   std::vector<std::string> rofiles(kReadOnlyEntries);
   for (bf::directory_iterator file(src_dir);
@@ -234,29 +234,29 @@ bool DeleteSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
       file != bf::directory_iterator();
       ++file) {
     bf::path current(file->path());
-    if (bf::is_symlink(symlink_status(current))) {
-      bf::path resolved_path = bf::read_symlink(current, error);
-      if (error) {
-        LOG(ERROR) << "Getting resolved path of symlink: " << current;
-        LOG(ERROR) << "resolved_path: " << resolved_path;
-        LOG(ERROR) << "error: " << error.message();
-        return false;
-      }
-      LOG(DEBUG) << "resolved_path: " << resolved_path;
-      bf::path parent = resolved_path.parent_path();
-      if (!parent.empty() && (parent == src_dir)) {
-        bf::remove(current, error);
-        if (error) {
-          LOG(ERROR) << "Symlink deletion failure for: " << current
-                     << ", error: " << error.message();
-          return false;
-        }
-        LOG(DEBUG) << "removed: " << current;
-      } else {
-        LOG(WARNING) << "Parent is empty or not equal to src, parenet: ("
+    if (!bf::is_symlink(symlink_status(current)))
+      continue;
+    bf::path resolved_path = bf::read_symlink(current, error);
+    if (error) {
+      LOG(ERROR) << "Failed to get resolved path of symlink: " << current
+                 << ", error: " << error.message();
+      return false;
+    }
+
+    LOG(DEBUG) << "resolved_path: " << resolved_path;
+    bf::path parent = resolved_path.parent_path();
+    if (parent.empty() || (parent != src_dir)) {
+      LOG(WARNING) << "Parent is empty or not equal to src, parent: ("
                    << parent << ")";
-      }
+      continue;
+    }
+    bf::remove(current, error);
+    if (error) {
+      LOG(ERROR) << "Symlink deletion failure for: " << current
+                  << ", error: " << error.message();
+      return false;
     }
+    LOG(DEBUG) << "removed: " << current;
   }
   bf::path shared_res = dst_dir / kSharedResDir;
   if (bf::is_symlink(symlink_status(shared_res))) {
@@ -270,43 +270,38 @@ bool DeleteSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
   return true;
 }
 
-bool CreateStorageDirectories(const boost::filesystem::path& path,
-                              const std::string& api_version,
+bool CreateStorageDirectories(const boost::filesystem::path& root_path,
+                              const std::string& pkgid,
                               bool trusted, bool shareddata,
                               const std::vector<const char*> additional_dirs) {
-  if (!bf::exists(path)) {
-    LOG(DEBUG) << "Creating directories in: " << path;
-    bs::error_code error;
-    bf::create_directories(path, error);
-    if (error) {
-      LOG(ERROR) << "Failed to create directory: " << path;
-      return false;
-    }
+  bf::path path(root_path / pkgid);
+  if (!ci::CreateDir(path)) {
+    LOG(ERROR) << "Failed to create dir: " << path;
+    return false;
   }
 
-  utils::VersionNumber api_ver(api_version);
   std::vector<const char*> dirs(kEntries);
   dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
   if (trusted)
     dirs.push_back(kSharedTrustedDir);
-  if (api_ver < ver30 || shareddata) {
-    dirs.push_back(kSharedDataDir);
-  } else {
-    bf::path shared_data_path = path / kSharedDataDir;
-    // remove shared/data (deprecated)
-    if (!ci::RemoveAll(shared_data_path))
-      return false;
-  }
+
+  bs::error_code error;
   for (auto& entry : dirs) {
-    bs::error_code error;
     bf::path subpath = path / entry;
-    bf::create_directories(subpath, error);
-    if (error && !bf::exists(subpath)) {
+    if (!ci::CreateDir(subpath)) {
       LOG(ERROR) << "Failed to create directory: " << subpath;
       return false;
     }
   }
 
+  if (shareddata) {
+    if (!CreateSharedDataDirectories(root_path, pkgid))
+      return false;
+  } else {
+    if (!DeleteSharedDataDirectories(root_path, pkgid))
+      return false;
+  }
+
   bf::path shared_cache_path = path / kSharedCacheDir;
   // remove shared/cache (do not support)
   if (!ci::RemoveAll(shared_cache_path))
@@ -315,6 +310,70 @@ bool CreateStorageDirectories(const boost::filesystem::path& path,
   return true;
 }
 
+bool BackupSharedDataDirectories(const bf::path& apps_rw,
+    const std::string& pkgid) {
+  if (!ci::MakeBackup(apps_rw / pkgid / kSharedDataDir))
+    return false;
+  if (!ci::MakeBackup(apps_rw / kSharedDir / pkgid))
+    return false;
+  if (!ci::MakeBackup(apps_rw / kSharedTmpDir / pkgid))
+    return false;
+  return true;
+}
+
+bool RestoreSharedDataDirectories(const bf::path& apps_rw,
+    const std::string& pkgid) {
+  if (!ci::RestoreBackup(apps_rw / pkgid / kSharedDataDir))
+    return false;
+  if (!ci::RestoreBackup(apps_rw / kSharedDir / pkgid))
+    return false;
+  if (!ci::RestoreBackup(apps_rw / kSharedTmpDir / pkgid))
+    return false;
+  return true;
+}
+
+bool RemoveBackupSharedDataDirectories(const bf::path& apps_rw,
+    const std::string& pkgid) {
+  if (!ci::RemoveBackup(apps_rw / pkgid / kSharedDataDir))
+    return false;
+  if (!ci::RemoveBackup(apps_rw / kSharedDir / pkgid))
+    return false;
+  if (!ci::RemoveBackup(apps_rw / kSharedTmpDir / pkgid))
+    return false;
+  return true;
+}
+
+bool CreateExternalUserDirectories(uid_t user, const std::string& pkgid,
+    const std::string& apps_prefix) {
+  boost::optional<gid_t> gid = ci::GetGidByUid(user);
+  if (!gid)
+    return false;
+
+  std::string group_name = ci::GetGroupNameByGid(*gid);
+  if (group_name != tzplatform_getenv(TZ_SYS_USER_GROUP)) {
+    LOG(ERROR) << "Failed to get group name of gid: " << *gid;
+    return false;
+  }
+
+  LOG(DEBUG) << "Creating directories for uid: " << user << ", gid: "
+             << *gid;
+
+  bf::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
+  if (apps_rw.empty()) {
+    LOG(DEBUG) << "Directory not exists: " << apps_rw;
+    return false;
+  }
+
+  if (!CreateStorageDirectories(apps_rw, pkgid, true, false,
+          std::vector<const char*>()))
+    return false;
+
+  if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, user))
+    return false;
+
+  return true;
+}
+
 }  // namespace
 
 namespace common_installer {
@@ -334,7 +393,6 @@ bool PerformExternalDirectoryCreationForUser(uid_t user,
                                              const std::string& pkgid) {
   bf::path storage_path = GetExternalCardPath();
 
-  const bool set_permissions = false;
   if (!bf::exists(storage_path)) {
     LOG(WARNING) << "External storage (SD Card) is not mounted.";
     return false;
@@ -351,8 +409,27 @@ bool PerformExternalDirectoryCreationForUser(uid_t user,
     }
   }
 
-  CreateUserDirectories(user, pkgid,
-                            storage_apps_path.c_str(), set_permissions);
+  if (CreateExternalUserDirectories(user, pkgid, storage_apps_path.string()))
+    return false;
+
+  for (auto& lw_user : GetLightUserList(user)) {
+    bf::path storage_apps_lw_path = storage_apps_path
+        / kSubssesionDir / lw_user / "apps";
+    if (!bf::exists(storage_apps_lw_path)) {
+      bs::error_code error;
+      bf::create_directories(storage_apps_lw_path, error);
+      if (error) {
+        LOG(ERROR) << "Failed to create directory: "
+                   << storage_apps_lw_path.c_str();
+        return false;
+      }
+    }
+
+    if (CreateExternalUserDirectories(user, pkgid,
+        storage_apps_lw_path.string()))
+      return false;
+  }
+
   return true;
 }
 
@@ -366,13 +443,25 @@ bool PerformExternalDirectoryDeletionForUser(uid_t user,
   }
 
   bf::path storage_apps_path = bf::path(storage_path) / "apps";
-  return DeleteDirectories(
-      GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid);
+  if (!DeleteDirectories(
+      GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid))
+    return false;
+
+  for (auto& lw_user : GetLightUserList(user)) {
+    bf::path storage_apps_lw_path =
+        storage_apps_path / kSubssesionDir / lw_user / "apps";
+    if (!DeleteDirectories(
+            GetDirectoryPathForStorage(user, storage_apps_lw_path.string()),
+            pkgid))
+      return false;
+  }
+
+  return true;
 }
 
 bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
   UserList list = ci::GetUserList();
-  for (auto l : list) {
+  for (const auto& l : list) {
     if (!PerformExternalDirectoryCreationForUser(std::get<0>(l),
                                                  pkgid))
       LOG(WARNING) << "Could not create external storage directories for user: "
@@ -383,7 +472,7 @@ bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
 
 bool PerformExternalDirectoryCreationForAllPkgs() {
   UserList list = ci::GetUserList();
-  for (auto l  : list) {
+  for (const auto& l  : list) {
     uid_t uid = std::get<0>(l);
     pkgmgrinfo_pkginfo_filter_h filter_handle = nullptr;
     int ret = pkgmgrinfo_pkginfo_filter_create(&filter_handle);
@@ -398,14 +487,14 @@ bool PerformExternalDirectoryCreationForAllPkgs() {
 
     ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(filter_handle,
         [](const pkgmgrinfo_pkginfo_h handle, void* user_data) -> int {
-          uid_t uid =
+          uid_t u =
               static_cast<uid_t>(reinterpret_cast<uintptr_t>(user_data));
           char* pkgid = nullptr;
 
-          int ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
-          if (ret != PMINFO_R_OK)
+          int r = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
+          if (r != PMINFO_R_OK)
             return -1;
-          if (!PerformExternalDirectoryCreationForUser(uid, pkgid))
+          if (!PerformExternalDirectoryCreationForUser(u, pkgid))
             return -1;
 
           return 0;
@@ -424,7 +513,7 @@ bool PerformExternalDirectoryCreationForAllPkgs() {
 
 bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
   UserList list = ci::GetUserList();
-  for (auto l : list) {
+  for (const auto& l : list) {
     uid_t uid = std::get<0>(l);
     ci::PkgQueryInterface pkg_query(pkgid, uid);
     LOG(DEBUG) << "Deleting directories for user: " << uid;
@@ -441,127 +530,171 @@ bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
   return true;
 }
 
-bool CreateStorageDirectories(const boost::filesystem::path& path,
-                              const std::string& pkgid, uid_t uid,
-                              const std::string& api_version,
-                              bool trusted, bool shareddata) {
-  if (!::CreateStorageDirectories(path, api_version, trusted, shareddata,
-                                  std::vector<const char*>())) {
-    LOG(ERROR) << "Failed to create storage directory for path: " << path;
+bool CreatePerUserStorageDirectories(const std::string& pkgid, bool trusted,
+    bool shareddata, bool is_readonly,
+    const std::vector<const char*> additional_dirs) {
+  // create skel dir
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!::CreateStorageDirectories(skel_apps_rw, pkgid, trusted, shareddata,
+          additional_dirs)) {
+    LOG(ERROR) << "Failed to create skeleton storage directories";
     return false;
   }
 
   std::string error_message;
-  if (!RegisterSecurityContextForPath(pkgid, path, uid, false,
-                                      &error_message)) {
-    LOG(ERROR) << "Failed to register security context for path: " << path
-               << ", error_message: " << error_message;
+  if (!RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
+          kGlobalUserUid, is_readonly, &error_message)) {
+    LOG(ERROR) << "Failed to register security context for path: "
+               << skel_apps_rw / pkgid << ", error_message: " << error_message;
     return false;
   }
 
-  return true;
-}
-
-bool DeleteStorageDirectories(const boost::filesystem::path& path) {
-  std::vector<const char*> dirs;
-  dirs.assign(kEntries.begin() + 1, kEntries.end());
-  dirs.push_back(kSharedTrustedDir);
-  dirs.push_back(kSharedDataDir);
-  dirs.push_back(kSharedCacheDir);
-  for (auto& entry : dirs) {
-    bf::path subpath = path / entry;
-    if (!ci::RemoveAll(subpath))
+  if (!is_readonly) {
+    bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+    if (!CreateSymlinkFiles(src_dir, skel_apps_rw / pkgid))
       return false;
   }
-  return true;
-}
 
-bool CreateSkelDirectories(const std::string& pkgid,
-                           const std::string& api_version,
-                           bool trusted, bool shareddata, bool is_readonly,
-                           const std::vector<const char*> additional_dirs) {
-  bf::path path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
-                  bf::path(kSkelAppDir) / pkgid;
-  LOG(DEBUG) << "Creating directories in: " << path;
+  // create per user dir
+  UserList list = ci::GetUserList();
+  for (const auto& l : list) {
+    uid_t uid = std::get<0>(l);
+    bf::path owner_apps_rw = std::get<2>(l) / "apps_rw";
+    std::vector<bf::path> apps_rw_paths;
+    apps_rw_paths.push_back(std::move(owner_apps_rw));
+
+    for (auto& lw_user : GetLightUserList(uid))
+      apps_rw_paths.push_back(std::get<2>(l)
+          / kSubssesionDir / lw_user / "apps_rw");
+
+    LOG(DEBUG) << "Creating directories for user: " << uid;
+    for (auto& apps_rw : apps_rw_paths) {
+      if (!::CreateStorageDirectories(apps_rw, pkgid, trusted, shareddata,
+          additional_dirs)) {
+        LOG(ERROR) << "Failed to create storage directory for user: " << uid;
+        return false;
+      }
 
-  if (!::CreateStorageDirectories(path, api_version, trusted, shareddata,
-                                  additional_dirs)) {
-    LOG(ERROR) << "Failed to create storage directory for path: " << path;
-    return false;
-  }
+      if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
+        return false;
 
-  std::string error_message;
-  if (!RegisterSecurityContextForPath(pkgid, path, kGlobalUserUid,
-                                      is_readonly, &error_message)) {
-    LOG(ERROR) << "Failed to register security context for path: " << path
-               << ", error_message: " << error_message;
-    return false;
-  }
+      if (shareddata) {
+        std::vector<std::string> shared_dirs(kSharedDataEntries);
+        for (const auto& entry : shared_dirs) {
+          bf::path shared_dst = apps_rw / entry / pkgid;
+          if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
+            return false;
+        }
+      }
 
-  bool result = true;
-  if (!is_readonly) {
-    bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
-    result = CreateSymlinkFiles(src_dir, path);
+      if (!RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid, false,
+                                          &error_message)) {
+        LOG(ERROR) << "Failed to register security context for path: "
+                   << apps_rw / pkgid << ", error_message: " << error_message;
+        return false;
+      }
+    }
   }
 
-  return result;
+  return true;
 }
 
-bool UpdateSkelDirectories(const std::string& pkgid,
-                           bool is_remove_shareddata) {
-  bf::path path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
-                  bf::path(kSkelAppDir) / pkgid;
-  bf::path shared_data_path = path / kSharedDataDir;
-  LOG(DEBUG) << ((is_remove_shareddata) ? "Removing" : "Creating")
-             << " directory : " << shared_data_path;
+bool DeletePerUserStorageDirectories(const std::string& pkgid,
+    bool keep_rwdata) {
+  // delete skel dir
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!ci::RemoveAll(skel_apps_rw / pkgid)) {
+    LOG(ERROR) << "Failed to delete skeleton storage directories";
+    return false;
+  }
 
-  if (!is_remove_shareddata) {
-    if (!CreateDir(shared_data_path))
-      return false;
+  if (keep_rwdata)
+    return true;
 
-    std::string error_message;
-    if (!RegisterSecurityContextForPath(pkgid, path, kGlobalUserUid,
-                                        false, &error_message)) {
-      LOG(ERROR) << "Failed to register security context for path: " << path
-                 << ", error_message: " << error_message;
-      return false;
+  // delete per user dir
+  UserList list = ci::GetUserList();
+  for (const auto& l : list) {
+    uid_t uid = std::get<0>(l);
+    bf::path owner_apps_rw = std::get<2>(l) / "apps_rw";
+    std::vector<bf::path> apps_rw_paths;
+    apps_rw_paths.push_back(std::move(owner_apps_rw));
+
+    for (auto& lw_user : GetLightUserList(uid))
+      apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
+                              "apps_rw");
+
+    LOG(DEBUG) << "Deleting directories for user: " << uid;
+    for (auto& apps_rw : apps_rw_paths) {
+      if (!ci::RemoveAll(apps_rw / pkgid)) {
+        LOG(ERROR) << "Failed to delete storage directory for user: " << uid;
+        return false;
+      }
     }
-  } else {
-    return ci::RemoveAll(shared_data_path);
   }
+
+  if (!ci::DeletePerUserSharedDataDir(pkgid)) {
+    LOG(ERROR) << "Failed to delete per user shared data dir";
+    return false;
+  }
+
   return true;
 }
 
-bool DeleteSkelDirectories(const std::string& pkgid) {
-  bf::path path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
-                  bf::path(kSkelAppDir);
-  return DeleteDirectories(path, pkgid);
-}
+bool CreateStorageDirectories(const boost::filesystem::path& path,
+                              const std::string& pkgid, uid_t uid,
+                              bool trusted, bool shareddata) {
+  if (!::CreateStorageDirectories(path, pkgid, trusted,
+                                  shareddata, std::vector<const char*>())) {
+    LOG(ERROR) << "Failed to create storage directory for path: " << path;
+    return false;
+  }
 
+  if (!::SetPackageDirectoryOwnerAndPermissions(path / pkgid, uid))
+    return false;
 
-bool DeleteUserDirectories(const std::string& pkgid) {
-  UserList list = ci::GetUserList();
-  for (auto l : list) {
-    uid_t uid = std::get<0>(l);
-    ci::PkgQueryInterface pkg_query(pkgid, uid);
-    if (pkg_query.IsPackageInstalled()) {
-      LOG(INFO) << pkgid << " is installed for user " << std::get<0>(l);
-      continue;
+  if (shareddata) {
+    std::vector<std::string> shared_dirs(kSharedDataEntries);
+    for (const auto& entry : shared_dirs) {
+      bf::path shared_dst = path / entry / pkgid;
+      if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
+        return false;
     }
+  }
 
-    LOG(DEBUG) << "Deleting directories of " << pkgid
-               << ", for uid: " << std::get<0>(l);
-    bf::path apps_rw(std::get<2>(l) / "apps_rw");
-    if (!DeleteDirectories(apps_rw, pkgid)) {
-      return false;
-    }
+  std::string error_message;
+  if (!RegisterSecurityContextForPath(pkgid, path / pkgid, uid, false,
+                                      &error_message)) {
+    LOG(ERROR) << "Failed to register security context for path: " << path
+               << ", error_message: " << error_message;
+    return false;
   }
+
   return true;
 }
 
+void RemoveRWDirectories(const boost::filesystem::path& root) {
+  if (!RemoveAll(root / kCache))
+    LOG(ERROR) << "Failed to remove packaged cache directory";
+  if (!RemoveAll(root / kData))
+    LOG(ERROR) << "Failed to remove packaged data directory";
+  if (!RemoveAll(root / kSharedCacheDir))
+    LOG(ERROR) << "Failed to remove packaged shared/cache directory";
+  if (!RemoveAll(root / kSharedDataDir))
+    LOG(ERROR) << "Failed to remove packaged shared/data directory";
+  if (!RemoveAll(root / kSharedTrustedDir))
+    LOG(ERROR) << "Failed to remove packaged shared/trusted directory";
+}
+
+bool DeleteSharedDirectories(const bf::path& path,
+                             const std::string& pkgid) {
+  return DeleteSharedDataDirectories(path, pkgid);
+}
+
 bool DeleteUserExternalDirectories(const std::string& pkgid) {
   UserList list = ci::GetUserList();
-  for (auto l : list) {
+  for (const auto& l : list) {
     uid_t uid = std::get<0>(l);
     ci::PkgQueryInterface pkg_query(pkgid, uid);
     if (pkg_query.IsPackageInstalled()) {
@@ -575,81 +708,14 @@ bool DeleteUserExternalDirectories(const std::string& pkgid) {
     if (!DeleteDirectories(apps_rw, pkgid)) {
       return false;
     }
-  }
-  return true;
-}
 
-
-bool CopyUserDirectories(const std::string& pkgid) {
-  UserList list = ci::GetUserList();
-  for (auto l : list) {
-    uid_t uid = std::get<0>(l);
-    LOG(DEBUG) << "Copying directories for uid: " << uid;
-    bf::path apps_rw(std::get<2>(l) / "apps_rw");
-    bf::path src = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
-                   bf::path(kSkelAppDir) / pkgid;
-    bf::path dst = apps_rw / pkgid;
-    if (!ci::CopyDir(src, dst, FSFlag::FS_NONE, true))
-      continue;
-    gid_t gid = std::get<1>(l);
-    if (!SetDirectoryOwnerAndPermissions(dst, uid, gid))
-      return false;
-    for (bf::recursive_directory_iterator iter(dst);
-        iter != bf::recursive_directory_iterator(); ++iter) {
-      if (!SetDirectoryOwnerAndPermissions(iter->path(),
-          uid, gid))
+    for (auto& lw_user : GetLightUserList(uid)) {
+      bf::path apps_rw_lw(std::get<2>(l) / kSubssesionDir / lw_user / "apps_rw");
+      if (!DeleteDirectories(apps_rw_lw, pkgid))
         return false;
     }
-    std::string error_message;
-    if (!RegisterSecurityContextForPath(pkgid, dst, uid,
-        false, &error_message)) {
-      LOG(ERROR) << "Failed to register security context for path: " << dst
-                 << ", error_message: " << error_message;
-      return false;
-    }
   }
-  return true;
-}
-
-bool UpdateUserDirectory(const std::string& pkgid, bool is_remove_shareddata) {
-  UserList list = ci::GetUserList();
-  for (auto l : list) {
-    bf::path apps_rw(std::get<2>(l) / "apps_rw");
-    bf::path root_dst = apps_rw / pkgid;
-    bf::path shareddir_dst = root_dst / kSharedDataDir;
-    uid_t uid = std::get<0>(l);
-    LOG(DEBUG) << ((is_remove_shareddata) ? "Deleting" : "Adding")
-               << " shareddata directory for uid: " << uid;
 
-    if (!is_remove_shareddata) {
-      bs::error_code error;
-      bf::create_directories(shareddir_dst, error);
-      if (error && !bf::exists(shareddir_dst)) {
-        LOG(ERROR) << "Failed to create directory: " << shareddir_dst;
-        return false;
-      }
-
-      gid_t gid = std::get<1>(l);
-      if (!SetDirectoryOwnerAndPermissions(root_dst, uid, gid))
-        return false;
-      for (bf::recursive_directory_iterator iter(root_dst);
-          iter != bf::recursive_directory_iterator(); ++iter) {
-        if (!SetDirectoryOwnerAndPermissions(iter->path(),
-            uid, gid))
-          return false;
-      }
-
-      std::string error_message;
-      if (!RegisterSecurityContextForPath(pkgid, root_dst, uid,
-          false, &error_message)) {
-        LOG(ERROR) << "Failed to register security context for path: "
-                   << root_dst << ", error_message: " << error_message;
-        return false;
-      }
-    } else {
-      return ci::RemoveAll(shareddir_dst);
-    }
-  }
   return true;
 }
 
@@ -660,24 +726,36 @@ bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
     return false;
   }
 
-  bool result = true;
   UserList list = ci::GetUserList();
-  for (auto l : list) {
+  for (const auto& l : list) {
     uid_t uid = std::get<0>(l);
     LOG(DEBUG) << "Creating symlinks for uid: " << uid;
     // check installed user private app.
     ci::PkgQueryInterface pkg_query(pkgid, uid);
     if (pkg_query.IsPackageInstalled())
       continue;
-    bf::path apps_rw(std::get<2>(l) / "apps_rw");
-    bf::path dst_dir = apps_rw / pkgid;
-    if (!bf::exists(dst_dir)) {
-      LOG(WARNING) << "dst_dir not exists";
-      continue;
+
+    bf::path owner_apps_rw = std::get<2>(l) / "apps_rw";
+    std::vector<bf::path> apps_rw_paths;
+    apps_rw_paths.push_back(std::move(owner_apps_rw));
+
+    for (auto& lw_user : GetLightUserList(uid))
+      apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
+                              "apps_rw");
+
+    for (auto& apps_rw : apps_rw_paths) {
+      bf::path dst_dir = apps_rw / pkgid;
+      if (!bf::exists(dst_dir)) {
+        LOG(WARNING) << "dst_dir not exists";
+        continue;
+      }
+
+      if (!CreateSymlinkFiles(src_dir, dst_dir))
+        return false;
     }
-    result = CreateSymlinkFiles(src_dir, dst_dir);
   }
-  return result;
+
+  return true;
 }
 
 bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
@@ -706,24 +784,36 @@ bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
     return true;
   }
 
-  bool result = true;
   UserList list = ci::GetUserList();
-  for (auto l : list) {
+  for (const auto& l : list) {
     uid_t uid = std::get<0>(l);
     LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
+
     // check installed user private app.
     ci::PkgQueryInterface pkg_query(pkgid, uid);
     if (pkg_query.IsPackageInstalled())
       continue;
-    bf::path apps_rw(std::get<2>(l) / "apps_rw");
-    bf::path dst_dir = apps_rw / pkgid;
-    if (!bf::exists(dst_dir)) {
-      LOG(WARNING) << "dst_dir not exists";
-      continue;
+
+    bf::path owner_apps_rw = std::get<2>(l) / "apps_rw";
+    std::vector<bf::path> apps_rw_paths;
+    apps_rw_paths.push_back(std::move(owner_apps_rw));
+    for (auto& lw_user : GetLightUserList(uid))
+      apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
+                              "apps_rw");
+
+    for (auto& apps_rw : apps_rw_paths) {
+      bf::path dst_dir = apps_rw / pkgid;
+      if (!bf::exists(dst_dir)) {
+        LOG(WARNING) << "dst_dir not exists";
+        continue;
+      }
+
+      if (!DeleteSymlinkFiles(src_dir, dst_dir))
+        return false;
     }
-    result = DeleteSymlinkFiles(src_dir, dst_dir);
   }
-  return result;
+
+  return true;
 }
 
 bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
@@ -745,39 +835,245 @@ bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
 }
 
 bool SetPackageDirectoryOwnerAndPermissions(const bf::path& path, uid_t uid) {
-  boost::optional<gid_t> gid = ci::GetGidByUid(uid);
-  if (!gid)
+  return ::SetPackageDirectoryOwnerAndPermissions(path, uid);
+}
+
+bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
+  if (bf::exists(kDisableLegacySharedDataDirSupport))
     return false;
-  bf::perms perms644 =
-      bf::owner_read | bf::owner_write | bf::group_read | bf::others_read;
-  bf::perms perms755 =
-      perms644 | bf::owner_exe | bf::group_exe | bf::others_exe;
-  for (bf::recursive_directory_iterator iter(path);
-      iter != bf::recursive_directory_iterator(); ++iter) {
-    if (bf::is_symlink(symlink_status(iter->path())) ||
-        (bf::is_directory(iter->path()) &&
-        (iter->path().filename() == ".mmc" ||
-            iter->path().filename() == ".pkg" ||
-            iter->path().filename() == "tep"))) {
-      // skip symlink or path which is related to
-      // mount or directory installer creates
-      continue;
-    } else if (bf::is_directory(iter->path())) {
-      // directories
-      if (!SetDirectoryOwnerAndPermissions(iter->path(), uid, *gid))
+  utils::VersionNumber api_ver(api_version);
+  if (api_ver < ver30)
+    return true;
+  else
+    return false;
+}
+
+bool CreateSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  if (!CreateSharedDataDirectories(apps_rw, pkgid))
+    return false;
+
+  bf::path path = apps_rw / pkgid;
+  std::string error_message;
+  if (!ci::RegisterSecurityContextForPath(pkgid, path, uid, false,
+          &error_message)) {
+    LOG(ERROR) << "Failed to register security context for path: " << path
+               << ", error_message: " << error_message;
+    return false;
+  }
+
+  return true;
+}
+
+bool CreatePerUserSharedDataDir(const std::string& pkgid) {
+  // create skel dir
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  LOG(DEBUG) <<  "Creating directory : " << skel_apps_rw;
+  if (!CreateSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  std::string error_message;
+  if (!ci::RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
+          kGlobalUserUid, false, &error_message)) {
+    LOG(ERROR) << "Failed to register security context for path: "
+               << skel_apps_rw / pkgid << ", error_message: " << error_message;
+    return false;
+  }
+
+  // create per user dir
+  ci::UserList list = ci::GetUserList();
+  for (const auto& l : list) {
+    uid_t uid = std::get<0>(l);
+    LOG(DEBUG) << "Adding shareddata directory for uid: " << uid;
+
+    bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<bf::path> apps_rw_paths;
+    apps_rw_paths.push_back(std::move(owner_apps_rw));
+    for (auto& lw_user : GetLightUserList(uid))
+      apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
+                              "apps_rw");
+
+    for (auto& apps_rw : apps_rw_paths) {
+      if (!CreateSharedDataDirectories(apps_rw, pkgid))
         return false;
-    } else if (iter.level() == 1 &&
-        iter->path().parent_path().filename() == "bin") {
-      // bin files
-      if (!SetDirOwnershipAndPermissions(iter->path(), perms755, uid, *gid))
+
+      std::vector<std::string> shared_dirs(kSharedDataEntries);
+      for (const auto& entry : shared_dirs) {
+        bf::path shared_dst = apps_rw / entry / pkgid;
+        if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
+          return false;
+      }
+
+      if (!ci::RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
+                                              false, &error_message)) {
+        LOG(ERROR) << "Failed to register security context for path: "
+                   << apps_rw / pkgid << ", error_message: " << error_message;
         return false;
-    } else {
-      // other files
-      if (!SetDirOwnershipAndPermissions(iter->path(), perms644, uid, *gid))
+      }
+    }
+  }
+
+  return true;
+}
+
+bool DeleteSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  return DeleteSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool DeletePerUserSharedDataDir(const std::string& pkgid) {
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!DeleteSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  ci::UserList list = ci::GetUserList();
+  for (const auto& l : list) {
+    uid_t uid = std::get<0>(l);
+
+    bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<bf::path> apps_rw_paths;
+    apps_rw_paths.push_back(std::move(owner_apps_rw));
+    for (auto& lw_user : GetLightUserList(uid))
+      apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
+                              "apps_rw");
+
+    for (auto& apps_rw : apps_rw_paths) {
+      if (!DeleteSharedDataDirectories(apps_rw, pkgid))
         return false;
     }
   }
   return true;
 }
 
+bool BackupSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  return BackupSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool BackupPerUserSharedDataDir(const std::string& pkgid) {
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!BackupSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  ci::UserList list = ci::GetUserList();
+  for (const auto& l : list) {
+    uid_t uid = std::get<0>(l);
+    bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<bf::path> apps_rw_paths;
+    apps_rw_paths.push_back(std::move(owner_apps_rw));
+    for (auto& lw_user : GetLightUserList(uid))
+      apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
+                              "apps_rw");
+
+    for (auto& apps_rw : apps_rw_paths) {
+      if (!BackupSharedDataDirectories(apps_rw, pkgid))
+        return false;
+    }
+  }
+
+  return true;
+}
+
+bool RestoreSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  if (!RestoreSharedDataDirectories(apps_rw, pkgid))
+    return false;
+
+  if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
+    return false;
+
+  std::vector<std::string> shared_dirs(kSharedDataEntries);
+  for (const auto& entry : shared_dirs) {
+    bf::path shared_dst = apps_rw / entry / pkgid;
+    if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
+      return false;
+  }
+
+  std::string error_message;
+  if (!RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid, false,
+                                      &error_message)) {
+    LOG(ERROR) << "Failed to register security context for path: " << apps_rw
+               << ", error_message: " << error_message;
+    return false;
+  }
+
+  return true;
+}
+
+bool RestorePerUserSharedDataDir(const std::string& pkgid) {
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!RestoreSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  std::string error_message;
+  ci::UserList list = ci::GetUserList();
+  for (const auto& l : list) {
+    uid_t uid = std::get<0>(l);
+    bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<bf::path> apps_rw_paths;
+    apps_rw_paths.push_back(std::move(owner_apps_rw));
+    for (auto& lw_user : GetLightUserList(uid))
+      apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
+                              "apps_rw");
+
+    for (auto& apps_rw : apps_rw_paths) {
+      if (!RestoreSharedDataDirectories(apps_rw, pkgid))
+        return false;
+
+      if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
+        return false;
+
+      std::vector<std::string> shared_dirs(kSharedDataEntries);
+      for (const auto& entry : shared_dirs) {
+        bf::path shared_dst = apps_rw / entry / pkgid;
+        if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
+          return false;
+      }
+
+      if (!RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
+              false, &error_message)) {
+        LOG(ERROR) << "Failed to register security context for path: "
+                   << apps_rw / pkgid << ", error_message: " << error_message;
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool RemoveBackupSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  return RemoveBackupSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool RemoveBackupPerUserSharedDataDir(const std::string& pkgid) {
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!RemoveBackupSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  ci::UserList list = ci::GetUserList();
+  for (const auto& l : list) {
+    uid_t uid = std::get<0>(l);
+    bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<bf::path> apps_rw_paths;
+    apps_rw_paths.push_back(std::move(owner_apps_rw));
+    for (auto& lw_user : GetLightUserList(uid))
+      apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
+                              "apps_rw");
+
+    for (auto& apps_rw : apps_rw_paths) {
+      if (!RemoveBackupSharedDataDirectories(apps_rw, pkgid))
+        return false;
+    }
+  }
+
+  return true;
+}
+
 }  // namespace common_installer