Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / shared_dirs.cc
index ef1dd10..c0f0641 100644 (file)
 
 #include "common/shared_dirs.h"
 
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-#include <boost/program_options.hpp>
-#include <boost/system/error_code.hpp>
+#include <manifest_parser/utils/logging.h>
+#include <manifest_parser/utils/version_number.h>
 
 #include <glib.h>
 #include <gio/gio.h>
-#include <manifest_parser/utils/logging.h>
 #include <vcore/Certificate.h>
 #include <pkgmgr-info.h>
-#include <pwd.h>
-#include <grp.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <tzplatform_config.h>
 #include <sys/xattr.h>
-#include <gum/gum-user.h>
-#include <gum/gum-user-service.h>
-#include <gum/common/gum-user-types.h>
 
 #include <algorithm>
 #include <cassert>
 #include <cstring>
 #include <cstdio>
 #include <exception>
+#include <filesystem>
 #include <iterator>
+#include <optional>
 #include <regex>
 #include <string>
+#include <system_error>
 #include <utility>
 #include <vector>
 #include <tuple>
 
+#include "common/utils/paths.h"
 #include "common/security_registration.h"
-#include "common/pkgmgr_registration.h"
+#include "common/utils/pkgmgr_query.h"
 #include "common/utils/base64.h"
 #include "common/utils/file_util.h"
+#include "common/utils/user_util.h"
 #include "common/utils/glist_range.h"
 
-namespace bf = boost::filesystem;
-namespace bpo = boost::program_options;
-namespace bs = boost::system;
 namespace ci = common_installer;
+namespace fs = std::filesystem;
 
 namespace {
 
-typedef std::vector<std::tuple<uid_t, gid_t, bf::path>> user_list;
+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 = {
-  {"/"},
-  {"cache/"},
-  {"data/"},
-  {"shared/"},
-  {"shared/cache/"},
+  {"shared"},
+  {"cache"},
+  {"data"},
+};
+const std::vector<std::string> kReadOnlyEntries = {
+  {"bin"},
+  {"lib"},
+  {"res"},
+  {"shared/res"},
+};
+const std::vector<std::string> kSharedDataEntries = {
+  {".shared"},
+  {".shared_tmp"},
 };
 
-const char kTrustedDir[] = "shared/trusted";
-const char kSkelAppDir[] = "/etc/skel/apps_rw";
-const char kPackagePattern[] = R"(^[0-9a-zA-Z_-]+(\.?[0-9a-zA-Z_-]+)*$)";
-const char kExternalStorageDirPrefix[] = "SDCardA1/apps";
-const char kDBusServiceName[] = "org.tizen.pkgdir_tool";
-const char kDBusObjectPath[] = "/org/tizen/pkgdir_tool";
-const char kDBusInterfaceName[] = "org.tizen.pkgdir_tool";
-const int32_t kPWBufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
-const int32_t kGRBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
-
-bool ValidateTizenPackageId(const std::string& id) {
-  std::regex package_regex(kPackagePattern);
-  return std::regex_match(id, package_regex);
-}
-
-int PkgmgrListCallback(const pkgmgrinfo_pkginfo_h handle, void *user_data) {
-  auto pkgs = reinterpret_cast<ci::PkgList*>(user_data);
-  char* pkgid = nullptr;
-  if (pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid) != PMINFO_R_OK) {
-    return -1;
-  }
-  char* api_version;
-  if (pkgmgrinfo_pkginfo_get_api_version(handle, &api_version) != PMINFO_R_OK) {
-    return -1;
-  }
-  pkgmgrinfo_certinfo_h cert_handle;
-  if (pkgmgrinfo_pkginfo_create_certinfo(&cert_handle) != PMINFO_R_OK) {
-    return -1;
-  }
-  if (pkgmgrinfo_pkginfo_load_certinfo(pkgid, cert_handle, 0) != PMINFO_R_OK) {
-    pkgmgrinfo_pkginfo_destroy_certinfo(cert_handle);
-    return -1;
-  }
-  const char* author_cert;
-  if (pkgmgrinfo_pkginfo_get_cert_value(cert_handle, PMINFO_AUTHOR_SIGNER_CERT,
-      &author_cert) != PMINFO_R_OK) {
-    pkgmgrinfo_pkginfo_destroy_certinfo(cert_handle);
-    return -1;
-  }
-  if (author_cert) {
-    ValidationCore::Certificate cert(author_cert,
-        ValidationCore::Certificate::FORM_BASE64);
-    unsigned char* public_key;
-    size_t len;
-    cert.getPublicKeyDER(&public_key, &len);
-    std::string author_id =
-        ci::EncodeBase64(reinterpret_cast<const char*>(public_key));
-    pkgs->emplace_back(pkgid, api_version, author_id);
-  } else {
-    pkgs->emplace_back(pkgid, std::string(), std::string());
-  }
+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 fs::path& path, uid_t uid) {
+  std::optional<gid_t> gid = ci::GetGidByUid(uid);
+  if (!gid)
+    return false;
 
-  pkgmgrinfo_pkginfo_destroy_certinfo(cert_handle);
+  using fs::perms;
+  perms perms755 = perms::all ^ perms::group_write ^ perms::others_write;
+  perms perms644 = perms::owner_read | perms::owner_write |
+      perms::group_read | perms::others_read;
+  perms perms_setgid = perms755 | perms::set_gid;
 
-  return 0;
+  std::optional<gid_t> system_share =
+    ci::GetGidByGroupName(kSystemShareGroupName);
+  // root path
+  if (!ci::SetDirOwnershipAndPermissions(path, perms755, uid, *gid))
+    return false;
+
+  for (fs::recursive_directory_iterator iter(path);
+      iter != fs::recursive_directory_iterator(); ++iter) {
+    if (fs::is_symlink(symlink_status(iter->path()))) {
+      // skip symlink path
+      continue;
+    } else if (fs::is_directory(iter->path()) && iter.depth() == 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 (fs::is_directory(iter->path())) {
+      bool is_rw = false;
+      if (iter.depth() == 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;
+    } else {
+      bool is_bin = false;
+      if (iter.depth() == 1 && iter->path().parent_path().filename() == "bin")
+        is_bin = true;
+      if (!ci::SetDirOwnershipAndPermissions(
+              iter->path(), is_bin ? perms755 : perms644, uid, *gid))
+        return false;
+    }
+  }
+  return true;
 }
 
-ci::PkgList GetAllGlobalAppsInformation() {
-  ci::PkgList pkgs;
-  if (pkgmgrinfo_pkginfo_get_usr_list(&PkgmgrListCallback,
-      &pkgs, tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)) != PMINFO_R_OK) {
-    LOG(ERROR) << "Failed to query global application list";
+fs::path GetDirectoryPathForStorage(uid_t user, std::string apps_prefix) {
+  std::string username = ci::GetUsernameByUid(user);
+  if (username.empty())
     return {};
-  }
-  return pkgs;
+
+  fs::path apps_rw;
+  apps_rw = fs::path(apps_prefix.c_str()) / username / "apps_rw";
+  return apps_rw;
 }
 
-ci::PkgList GetPkgInformation(uid_t uid, const std::string& pkgid) {
-  if (!ValidateTizenPackageId(pkgid)) {
-    LOG(DEBUG) << "Package id validation failed. pkgid = " << pkgid;
-    return ci::PkgList();
-  }
+bool DeleteSharedDataDirectories(const fs::path& path,
+                                 const std::string& pkgid) {
+  if (!ci::RemoveAll(path / pkgid / kSharedDataDir))
+    return false;
 
-  ci::PkgList pkgs;
-  pkgmgrinfo_pkginfo_h handle;
-  if (pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid.c_str(), uid, &handle) !=
-      PMINFO_R_OK) {
-    LOG(DEBUG) << "pkgmgrinfo_pkginfo_get_pkginfo failed, for pkgid=" << pkgid;
-    return {};
-  }
-  if (PkgmgrListCallback(handle, &pkgs) != 0) {
-    pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
-    LOG(DEBUG) << "PkgmgrListCallback failed";
-    return {};
+  std::vector<std::string> shared_dirs(kSharedDataEntries);
+  for (const auto& entry : shared_dirs) {
+    if (!ci::RemoveAll(path / entry / pkgid))
+      return false;
   }
-  pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
-  return pkgs;
+
+  return true;
 }
 
-bool SetPackageDirectoryOwnerAndPermissions(const bf::path& subpath, uid_t uid,
-                                            gid_t gid) {
-  bs::error_code error;
-  bf::perms perms = bf::owner_read |
-                    bf::owner_write |
-                    bf::group_read;
-  if (bf::is_directory(subpath)) {
-    perms |= bf::owner_exe | bf::group_exe | bf::others_exe;
-  }
-  bf::permissions(subpath, perms, error);
+bool CreateSharedDataDirectories(const fs::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;
+
+  fs::current_path(path / pkgid / kShared);
+  if (fs::exists(path / pkgid / kShared / kData))
+    return true;
+  fs::path relative_path = fs::relative(path / kSharedDir / pkgid / kData,
+      fs::current_path());
+  std::error_code error;
+  fs::create_symlink(relative_path, kData, error);
   if (error) {
-    LOG(ERROR) << "Failed to set permissions for: " << subpath;
+    LOG(ERROR) << "Failed to create symlink : " << error.message();
     return false;
   }
-  int ret = chown(subpath.c_str(), uid, gid);
-  if (ret != 0) {
-    LOG(ERROR) << "Failed to change owner of: " << subpath;
+
+  return true;
+}
+
+bool DeleteDirectories(const fs::path& app_dir, const std::string& pkgid) {
+  fs::path base_dir = app_dir / pkgid;
+  if (!ci::RemoveAll(base_dir))
+    return false;
+  if (!DeleteSharedDataDirectories(app_dir, pkgid))
     return false;
-  }
   return true;
 }
 
-bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
-                       const std::string& author_id,
-                       uid_t uid, gid_t gid, const bool set_permissions) {
-  bf::path base_dir = app_dir / pkgid;
-  if (bf::exists(base_dir)) {
-    LOG(DEBUG) << "Directory for user already exist: " << base_dir;
-    return true;
+bool CreateSymlinkFiles(const fs::path& src_dir, const fs::path& dst_dir) {
+  std::vector<std::string> rofiles(kReadOnlyEntries);
+  for (fs::directory_iterator file(src_dir);
+      file != fs::directory_iterator();
+      ++file) {
+    if (fs::is_regular_file(file->path())) {
+      fs::path current(file->path());
+      fs::path file_name = current.filename();
+      LOG(DEBUG) << "file_name: " << file_name;
+      rofiles.push_back(file_name.string());
+    }
   }
 
-  bs::error_code error;
-  std::vector<const char*> dirs(kEntries);
-  if (!author_id.empty())
-    dirs.push_back(kTrustedDir);
-  for (auto& entry : dirs) {
-    bf::path subpath = base_dir / entry;
-    bf::create_directories(subpath, error);
+  std::error_code error;
+  for (auto& entry : rofiles) {
+    fs::path src_path = src_dir / entry;
+    fs::path dst_path = dst_dir / entry;
+    if (!fs::exists(src_path)) {
+      // check if symlink for .mmc/bin,lib,res, then do not skip
+      if (!fs::is_symlink(symlink_status(src_path))) {
+        LOG(INFO) << "src_path not exist : " << src_path;
+        continue;
+      }
+    }
+    if (fs::exists(dst_path) || fs::is_symlink(symlink_status(dst_path))) {
+      LOG(WARNING) << "dst_path exist, skip : " << dst_path;
+      continue;
+    }
+    fs::create_symlink(src_path, dst_path, error);
     if (error) {
-      LOG(ERROR) << "Failed to create directory: " << subpath;
+      LOG(ERROR) << "Symlink creation failure src_path: " << src_path
+                 << " dst_path: " << dst_path;
+      LOG(ERROR) << "error: " << error.message();
       return false;
     }
+  }
+  return true;
+}
 
-    if (set_permissions) {
-      if (!SetPackageDirectoryOwnerAndPermissions(subpath, uid, gid))
-        return false;
+bool DeleteSymlinkFiles(const fs::path& src_dir, const fs::path& dst_dir) {
+  std::error_code error;
+  for (fs::directory_iterator file(dst_dir);
+      file != fs::directory_iterator();
+      ++file) {
+    fs::path current(file->path());
+    if (!fs::is_symlink(symlink_status(current)))
+      continue;
+    fs::path resolved_path = fs::read_symlink(current, error);
+    if (error) {
+      LOG(ERROR) << "Failed to get resolved path of symlink: " << current
+                 << ", error: " << error.message();
+      return false;
+    }
 
-      // for content
-      for (bf::recursive_directory_iterator iter(subpath);
-           iter != bf::recursive_directory_iterator(); ++iter) {
-        if (!SetPackageDirectoryOwnerAndPermissions(iter->path(), uid, gid))
+    LOG(DEBUG) << "resolved_path: " << resolved_path;
+    fs::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;
+    }
+    fs::remove(current, error);
+    if (error) {
+      LOG(ERROR) << "Symlink deletion failure for: " << current
+                  << ", error: " << error.message();
+      return false;
+    }
+    LOG(DEBUG) << "removed: " << current;
+  }
+  fs::path shared_res = dst_dir / kSharedResDir;
+  if (fs::is_symlink(symlink_status(shared_res))) {
+      fs::remove(shared_res, error);
+      if (error) {
+          LOG(ERROR) << "Symlink deletion failure for: " << shared_res
+                     << ", error: " << error.message();
           return false;
       }
-    }
   }
-
   return true;
 }
 
-bf::path GetDirectoryPathForStorage(uid_t user, std::string apps_prefix) {
-  struct passwd pwd;
-  struct passwd *pwd_result;
-  char buf[kPWBufSize];
-  int ret = getpwuid_r(user, &pwd, buf, sizeof(buf), &pwd_result);
-  if (ret != 0 || pwd_result == nullptr)
-    return {};
+bool CreateStorageDirectories(const fs::path& root_path,
+                              const std::string& pkgid,
+                              bool trusted, bool shareddata,
+                              const std::vector<const char*> additional_dirs) {
+  fs::path path(root_path / pkgid);
+  if (!ci::CreateDir(path)) {
+    LOG(ERROR) << "Failed to create dir: " << path;
+    return false;
+  }
 
-  bf::path apps_rw;
-  apps_rw = bf::path(apps_prefix.c_str()) / pwd.pw_name / "apps_rw";
+  std::vector<const char*> dirs(kEntries);
+  dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
+  if (trusted)
+    dirs.push_back(kSharedTrustedDir);
 
-  return apps_rw;
-}
+  std::error_code error;
+  for (auto& entry : dirs) {
+    fs::path subpath = path / entry;
+    if (!ci::CreateDir(subpath)) {
+      LOG(ERROR) << "Failed to create directory: " << subpath;
+      return false;
+    }
+  }
 
-bool CreateUserDirectories(uid_t user, const std::string& pkgid,
-    const std::string& author_id,
-    const std::string& apps_prefix, const bool set_permissions) {
-  struct passwd pwd;
-  struct passwd *pwd_result;
-  char buf_pw[kPWBufSize];
-  int ret = getpwuid_r(user, &pwd, buf_pw, sizeof(buf_pw), &pwd_result);
-  if (ret != 0 || pwd_result == nullptr) {
-    LOG(WARNING) << "Failed to get user for home directory: " << user;
-    return false;
+  if (shareddata) {
+    if (!CreateSharedDataDirectories(root_path, pkgid))
+      return false;
+  } else {
+    if (!DeleteSharedDataDirectories(root_path, pkgid))
+      return false;
   }
 
-  struct group gr;
-  struct group *gr_result;
-  char buf_gr[kGRBufSize];
-  ret = getgrgid_r(pwd.pw_gid, &gr, buf_gr, sizeof(buf_gr), &gr_result);
-  if (ret != 0
-      || strcmp(gr.gr_name, tzplatform_getenv(TZ_SYS_USER_GROUP)) != 0)
+  fs::path shared_cache_path = path / kSharedCacheDir;
+  // remove shared/cache (do not support)
+  if (!ci::RemoveAll(shared_cache_path))
     return false;
 
-  LOG(DEBUG) << "Creating directories for uid: " << pwd.pw_uid << ", gid: "
-             << pwd.pw_gid;
+  return true;
+}
 
-  bf::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
-  if (apps_rw.empty()) {
-    LOG(DEBUG) << "Directory not exists: " << apps_rw;
+bool BackupSharedDataDirectories(const fs::path& apps_rw,
+    const std::string& pkgid) {
+  if (!ci::MakeBackup(apps_rw / pkgid / kSharedDataDir))
     return false;
-  }
-
-  if (!CreateDirectories(apps_rw, pkgid, author_id,
-      pwd.pw_uid, pwd.pw_gid, set_permissions)) {
+  if (!ci::MakeBackup(apps_rw / kSharedDir / pkgid))
+    return false;
+  if (!ci::MakeBackup(apps_rw / kSharedTmpDir / pkgid))
     return false;
-  }
   return true;
 }
 
-bool DeleteDirectories(const bf::path& app_dir, const std::string& pkgid) {
-  bf::path base_dir = app_dir / pkgid;
-  bs::error_code error;
-  bf::remove_all(base_dir, error);
-  if (error) {
-    LOG(ERROR) << "Failed to delete directory: " << base_dir;
+bool RestoreSharedDataDirectories(const fs::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 RequestUserDirectoryOperation(const char* method,
+bool RemoveBackupSharedDataDirectories(const fs::path& apps_rw,
     const std::string& pkgid) {
-  GError* err = nullptr;
-  GDBusConnection* con = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
-  if (!con || err) {
-    LOG(WARNING) << "Failed to get dbus connection: " << err->message;
-    g_error_free(err);
+  if (!ci::RemoveBackup(apps_rw / pkgid / kSharedDataDir))
     return false;
-  }
-  GDBusProxy* proxy = g_dbus_proxy_new_sync(con, G_DBUS_PROXY_FLAGS_NONE,
-      nullptr, kDBusServiceName, kDBusObjectPath, kDBusInterfaceName, nullptr,
-      &err);
-  if (!proxy || err) {
-    LOG(ERROR) << "Failed to get dbus proxy: " << err->message;
-    g_error_free(err);
-    g_object_unref(con);
+  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) {
+  std::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;
   }
-  GVariant* r = g_dbus_proxy_call_sync(proxy, method,
-      g_variant_new("(s)", pkgid.c_str()), G_DBUS_CALL_FLAGS_NONE, -1, nullptr,
-      &err);
-  if (!r || err) {
-    LOG(ERROR) << "Failed to request: " << err->message;
-    g_error_free(err);
-    g_object_unref(proxy);
-    g_object_unref(con);
+
+  LOG(DEBUG) << "Creating directories for uid: " << user << ", gid: "
+             << *gid;
+
+  fs::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
+  if (apps_rw.empty()) {
+    LOG(DEBUG) << "Directory not exists: " << apps_rw;
     return false;
   }
-  bool result;
-  g_variant_get(r, "(b)", &result);
 
-  g_variant_unref(r);
-  g_object_unref(proxy);
-  g_object_unref(con);
+  if (!CreateStorageDirectories(apps_rw, pkgid, true, false,
+          std::vector<const char*>()))
+    return false;
 
-  return result;
-}
+  if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, user))
+    return false;
 
-user_list GetUserList() {
-  GumUserService* service =
-      gum_user_service_create_sync((getuid() == 0) ? TRUE : FALSE);
-  gchar** user_type_strv = gum_user_type_to_strv(
-      GUM_USERTYPE_ADMIN | GUM_USERTYPE_GUEST | GUM_USERTYPE_NORMAL);
-  GumUserList* gum_user_list =
-      gum_user_service_get_user_list_sync(service, user_type_strv);
-  user_list list;
-  for (GumUser* guser : GListRange<GumUser*>(gum_user_list)) {
-    uid_t uid;
-    g_object_get(G_OBJECT(guser), "uid", &uid, nullptr);
-    gid_t gid;
-    g_object_get(G_OBJECT(guser), "gid", &gid, nullptr);
-    gchar* homedir = nullptr;
-    g_object_get(G_OBJECT(guser), "homedir", &homedir, nullptr);
-    if (homedir == nullptr) {
-      LOG(WARNING) << "No homedir for uid: " << uid;
-      continue;
-    }
-    list.emplace_back(uid, gid, bf::path(homedir));
-  }
-  g_strfreev(user_type_strv);
-  gum_user_service_list_free(gum_user_list);
-  return list;
+  return true;
 }
 
 }  // namespace
@@ -343,88 +385,286 @@ std::string GetDirectoryPathForInternalStorage() {
 }
 
 std::string GetDirectoryPathForExternalStorage() {
-  const char* storage_path = tzplatform_mkpath(TZ_SYS_MEDIA,
-                                               kExternalStorageDirPrefix);
-  return std::string(storage_path);
-}
-
-bool PerformInternalDirectoryCreationForUser(uid_t user,
-                                             const std::string& pkgid,
-                                             const std::string& author_id) {
-  const char* internal_storage_prefix = tzplatform_getenv(TZ_SYS_HOME);
-  const bool set_permissions = true;
-  if (!CreateUserDirectories(user, pkgid, author_id,
-                             internal_storage_prefix, set_permissions))
-    return false;
-  return true;
+  return GetExternalCardPath().string();
 }
 
 bool PerformExternalDirectoryCreationForUser(uid_t user,
-                                             const std::string& pkgid,
-                                             const std::string& author_id) {
-  const char* storage_path = tzplatform_mkpath(TZ_SYS_MEDIA,
-                                               kExternalStorageDirPrefix);
-  const bool set_permissions = false;
-  if (!bf::exists(storage_path)) {
+                                             const std::string& pkgid) {
+  fs::path storage_path = GetExternalCardPath();
+
+  if (!fs::exists(storage_path)) {
     LOG(WARNING) << "External storage (SD Card) is not mounted.";
     return false;
   }
 
-  if (CreateUserDirectories(user, pkgid, author_id,
-                            storage_path, set_permissions)) {
+  fs::path storage_apps_path = storage_path / "apps";
+  if (!fs::exists(storage_apps_path)) {
+    std::error_code error;
+    fs::create_directories(storage_apps_path, error);
+    if (error) {
+      LOG(ERROR) << "Failed to create directory: "
+          << storage_apps_path.c_str();
+      return false;
+    }
+  }
+
+  if (CreateExternalUserDirectories(user, pkgid, storage_apps_path.string()))
+    return false;
+
+  for (auto& lw_user : GetLightUserList(user)) {
+    fs::path storage_apps_lw_path = storage_apps_path
+        / kSubssesionDir / lw_user / "apps";
+    if (!fs::exists(storage_apps_lw_path)) {
+      std::error_code error;
+      fs::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;
 }
 
-bool PerformInternalDirectoryCreationForAllUsers(const std::string& pkgid,
-                                                 const std::string& author_id) {
-  user_list list = GetUserList();
-  for (auto l : list) {
-    if (!PerformInternalDirectoryCreationForUser(std::get<0>(l),
-                                                 pkgid,
-                                                 author_id))
-      LOG(ERROR) << "Could not create internal storage directories for user: "
-                 << std::get<0>(l);
+bool PerformExternalDirectoryDeletionForUser(uid_t user,
+                                             const std::string& pkgid) {
+  fs::path storage_path = GetExternalCardPath();
+  if (!fs::exists(storage_path)) {
+    LOG(WARNING) << "External storage (SD Card) is not mounted. "
+        << "It will be ignored";
+    return true;
+  }
+
+  fs::path storage_apps_path = fs::path(storage_path) / "apps";
+  if (!DeleteDirectories(
+      GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid))
+    return false;
+
+  for (auto& lw_user : GetLightUserList(user)) {
+    fs::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,
-                                                 const std::string& author_id) {
-  user_list list = GetUserList();
-  for (auto l : list) {
+bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
+  UserList list = ci::GetUserList();
+  for (const auto& l : list) {
     if (!PerformExternalDirectoryCreationForUser(std::get<0>(l),
-                                                 pkgid,
-                                                 author_id))
+                                                 pkgid))
       LOG(WARNING) << "Could not create external storage directories for user: "
                    << std::get<0>(l);
   }
   return true;
 }
 
-bool CreateSkelDirectories(const std::string& pkgid) {
-  bf::path path = bf::path(kSkelAppDir) / pkgid;
-  LOG(DEBUG) << "Creating directories in: " << path;
-  bs::error_code error;
-  bf::create_directories(path, error);
+bool PerformExternalDirectoryCreationForAllPkgs() {
+  UserList list = ci::GetUserList();
+  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);
+    if (ret != PMINFO_R_OK)
+      return false;
+    ret = pkgmgrinfo_pkginfo_filter_add_string(filter_handle,
+        PMINFO_PKGINFO_PROP_PACKAGE_PRIVILEGE, kExternalStoragePrivilege);
+    if (ret != PMINFO_R_OK) {
+      pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
+      return false;
+    }
 
-  if (error) {
-    LOG(ERROR) << "Failed to create directory: " << path;
+    ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(filter_handle,
+        [](const pkgmgrinfo_pkginfo_h handle, void* user_data) -> int {
+          uid_t u =
+              static_cast<uid_t>(reinterpret_cast<uintptr_t>(user_data));
+          char* pkgid = nullptr;
+
+          int r = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
+          if (r != PMINFO_R_OK)
+            return -1;
+          if (!PerformExternalDirectoryCreationForUser(u, pkgid))
+            return -1;
+
+          return 0;
+        },
+        reinterpret_cast<void*>(static_cast<uintptr_t>(uid)));
+    if (ret != PMINFO_R_OK) {
+      LOG(DEBUG) << "Failed to create external directoy";
+      pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
+      return false;
+    }
+    pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
+  }
+
+  return true;
+}
+
+bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
+  UserList list = ci::GetUserList();
+  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;
+    if (pkg_query.IsPackageInstalled()) {
+      LOG(DEBUG) << "Package: " << pkgid << " for uid: " << uid
+                 << " still exists. Skipping";
+      continue;
+    }
+
+    if (!PerformExternalDirectoryDeletionForUser(uid, pkgid))
+      LOG(WARNING) << "Could not delete external storage directories for user: "
+                   << uid;
+  }
+  return true;
+}
+
+bool CreatePerUserStorageDirectories(const std::string& pkgid, bool trusted,
+    bool shareddata, bool is_readonly,
+    const std::vector<const char*> additional_dirs) {
+  // create skel dir
+  fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      fs::path(kSkelAppDir);
+  if (!::CreateStorageDirectories(skel_apps_rw, pkgid, trusted, shareddata,
+          additional_dirs)) {
+    LOG(ERROR) << "Failed to create skeleton storage directories";
     return false;
   }
 
-  for (auto& entry : kEntries) {
-    bf::path subpath = path / entry;
-    bf::create_directories(subpath, error);
-    if (error && !bf::exists(subpath)) {
-      LOG(ERROR) << "Failed to create directory: " << subpath;
+  std::string 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;
+  }
+
+  if (!is_readonly) {
+    fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+    if (!CreateSymlinkFiles(src_dir, skel_apps_rw / pkgid))
       return false;
+  }
+
+  // create per user dir
+  UserList list = ci::GetUserList();
+  for (const auto& l : list) {
+    uid_t uid = std::get<0>(l);
+    fs::path owner_apps_rw = std::get<2>(l) / "apps_rw";
+    std::vector<fs::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 (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
+        return false;
+
+      if (shareddata) {
+        std::vector<std::string> shared_dirs(kSharedDataEntries);
+        for (const auto& entry : shared_dirs) {
+          fs::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 DeletePerUserStorageDirectories(const std::string& pkgid,
+    bool keep_rwdata) {
+  // delete skel dir
+  fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      fs::path(kSkelAppDir);
+  if (!ci::RemoveAll(skel_apps_rw / pkgid)) {
+    LOG(ERROR) << "Failed to delete skeleton storage directories";
+    return false;
+  }
+
+  if (keep_rwdata)
+    return true;
+
+  // delete per user dir
+  UserList list = ci::GetUserList();
+  for (const auto& l : list) {
+    uid_t uid = std::get<0>(l);
+    fs::path owner_apps_rw = std::get<2>(l) / "apps_rw";
+    std::vector<fs::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;
+      }
+    }
+  }
+
+  if (!ci::DeletePerUserSharedDataDir(pkgid)) {
+    LOG(ERROR) << "Failed to delete per user shared data dir";
+    return false;
+  }
+
+  return true;
+}
+
+bool CreateStorageDirectories(const fs::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;
+
+  if (shareddata) {
+    std::vector<std::string> shared_dirs(kSharedDataEntries);
+    for (const auto& entry : shared_dirs) {
+      fs::path shared_dst = path / entry / pkgid;
+      if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
+        return false;
     }
   }
 
   std::string error_message;
-  if (!RegisterSecurityContextForPath(pkgid, path,
-      tzplatform_getuid(TZ_SYS_GLOBALAPP_USER), &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;
@@ -433,73 +673,406 @@ bool CreateSkelDirectories(const std::string& pkgid) {
   return true;
 }
 
-
-bool DeleteSkelDirectories(const std::string& pkgid) {
-  return DeleteDirectories(bf::path(kSkelAppDir), pkgid);
+void RemoveRWDirectories(const fs::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 fs::path& path,
+                             const std::string& pkgid) {
+  return DeleteSharedDataDirectories(path, pkgid);
+}
 
-bool DeleteUserDirectories(const std::string& pkgid) {
-  user_list list = GetUserList();
-  for (auto l : list) {
-    if (ci::IsPackageInstalled(pkgid, std::get<0>(l))) {
-      LOG(INFO) << pkgid << " is installed for user " << std::get<0>(l);
+bool DeleteUserExternalDirectories(const std::string& pkgid) {
+  UserList list = ci::GetUserList();
+  for (const 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 " << uid;
       continue;
     }
 
-    LOG(DEBUG) << "Deleting directories of " << pkgid
-               << ", for uid: " << std::get<0>(l);
-    bf::path apps_rw(std::get<2>(l) / "apps_rw");
+    LOG(DEBUG) << "Deleting external directories of " << pkgid
+               << ", for uid: " << uid;
+    fs::path apps_rw(std::get<2>(l) / "apps_rw");
     if (!DeleteDirectories(apps_rw, pkgid)) {
       return false;
     }
+
+    for (auto& lw_user : GetLightUserList(uid)) {
+      fs::path apps_rw_lw(std::get<2>(l) / kSubssesionDir / lw_user / "apps_rw");
+      if (!DeleteDirectories(apps_rw_lw, pkgid))
+        return false;
+    }
   }
+
   return true;
 }
 
+bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
+  fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+  if (!fs::exists(src_dir)) {
+    LOG(ERROR) << "src_dir not exists";
+    return false;
+  }
 
-bool CopyUserDirectories(const std::string& pkgid) {
-  user_list list = GetUserList();
-  for (auto l : list) {
-    LOG(DEBUG) << "Copying directories for uid: " << std::get<0>(l);
-    bf::path apps_rw(std::get<2>(l) / "apps_rw");
-    bf::path src = bf::path(kSkelAppDir) / pkgid;
-    bf::path dst = apps_rw / pkgid;
-    if (!ci::CopyDir(src, dst, FS_COPY_XATTR))
+  UserList list = ci::GetUserList();
+  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;
-    if (!SetPackageDirectoryOwnerAndPermissions(dst, std::get<0>(l),
-        std::get<1>(l)))
-      return false;
-    for (bf::recursive_directory_iterator iter(dst);
-        iter != bf::recursive_directory_iterator(); ++iter) {
-      if (!SetPackageDirectoryOwnerAndPermissions(iter->path(),
-          std::get<0>(l), std::get<1>(l)))
+
+    fs::path owner_apps_rw = std::get<2>(l) / "apps_rw";
+    std::vector<fs::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) {
+      fs::path dst_dir = apps_rw / pkgid;
+      if (!fs::exists(dst_dir)) {
+        LOG(WARNING) << "dst_dir not exists";
+        continue;
+      }
+
+      if (!CreateSymlinkFiles(src_dir, dst_dir))
         return false;
     }
   }
+
   return true;
 }
 
-bool RequestCopyUserDirectories(const std::string& pkgid) {
-  if (!RequestUserDirectoryOperation("CopyUserDirs", pkgid)) {
-    LOG(INFO) << "Try to copy user directories directly";
-    return CopyUserDirectories(pkgid);
+bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
+  fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+  if (!fs::exists(src_dir)) {
+    LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
+    return true;
+  }
+
+  tzplatform_set_user(uid);
+  fs::path dst_dir = fs::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
+  tzplatform_reset_user();
+  if (!fs::exists(dst_dir)) {
+    LOG(WARNING) << "dst_dir not exists";
+    return true;
+  }
+  bool result = CreateSymlinkFiles(src_dir, dst_dir);
+
+  return result;
+}
+
+bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
+  fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+  if (!fs::exists(src_dir)) {
+    LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
+    return true;
+  }
+
+  UserList list = ci::GetUserList();
+  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;
+
+    fs::path owner_apps_rw = std::get<2>(l) / "apps_rw";
+    std::vector<fs::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) {
+      fs::path dst_dir = apps_rw / pkgid;
+      if (!fs::exists(dst_dir)) {
+        LOG(WARNING) << "dst_dir not exists";
+        continue;
+      }
+
+      if (!DeleteSymlinkFiles(src_dir, dst_dir))
+        return false;
+    }
   }
+
   return true;
 }
 
-bool RequestDeleteUserDirectories(const std::string& pkgid) {
-  if (!RequestUserDirectoryOperation("DeleteUserDirs", pkgid)) {
-    LOG(INFO) << "Try to delete user directories directly";
-    return DeleteUserDirectories(pkgid);
+bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
+  fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+  if (!fs::exists(src_dir)) {
+    LOG(ERROR) << "src_dir not exists";
+    return false;
+  }
+
+  tzplatform_set_user(uid);
+  fs::path dst_dir = fs::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
+  tzplatform_reset_user();
+  if (!fs::exists(dst_dir)) {
+    LOG(WARNING) << "dst_dir not exists";
+    return true;
+  }
+  bool result = DeleteSymlinkFiles(src_dir, dst_dir);
+  return result;
+}
+
+bool SetPackageDirectoryOwnerAndPermissions(const fs::path& path, uid_t uid) {
+  return ::SetPackageDirectoryOwnerAndPermissions(path, uid);
+}
+
+bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
+  if (fs::exists(kDisableLegacySharedDataDirSupport))
+    return false;
+  utils::VersionNumber api_ver(api_version);
+  if (api_ver < ver30)
+    return true;
+  else
+    return false;
+}
+
+bool CreateSharedDataDir(const std::string& pkgid, uid_t uid) {
+  fs::path apps_rw = ci::GetRootAppPath(false, uid);
+  if (!CreateSharedDataDirectories(apps_rw, pkgid))
+    return false;
+
+  fs::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;
 }
 
-ci::PkgList CreatePkgInformationList(uid_t uid,
-                                     const std::vector<std::string>& pkgs) {
-  return pkgs.empty() ?
-      GetAllGlobalAppsInformation() : GetPkgInformation(uid, *pkgs.begin());
+bool CreatePerUserSharedDataDir(const std::string& pkgid) {
+  // create skel dir
+  fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      fs::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;
+
+    fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<fs::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;
+
+      std::vector<std::string> shared_dirs(kSharedDataEntries);
+      for (const auto& entry : shared_dirs) {
+        fs::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;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool DeleteSharedDataDir(const std::string& pkgid, uid_t uid) {
+  fs::path apps_rw = ci::GetRootAppPath(false, uid);
+  return DeleteSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool DeletePerUserSharedDataDir(const std::string& pkgid) {
+  fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      fs::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);
+
+    fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<fs::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) {
+  fs::path apps_rw = ci::GetRootAppPath(false, uid);
+  return BackupSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool BackupPerUserSharedDataDir(const std::string& pkgid) {
+  fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      fs::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);
+    fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<fs::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) {
+  fs::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) {
+    fs::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) {
+  fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      fs::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);
+    fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<fs::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) {
+        fs::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) {
+  fs::path apps_rw = ci::GetRootAppPath(false, uid);
+  return RemoveBackupSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool RemoveBackupPerUserSharedDataDir(const std::string& pkgid) {
+  fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      fs::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);
+    fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
+    std::vector<fs::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