symlink control for read-only files of global app. 93/81493/26 accepted/tizen/common/20160817.133206 accepted/tizen/common/20160818.144522 accepted/tizen/ivi/20160819.063353 accepted/tizen/mobile/20160819.063231 accepted/tizen/tv/20160819.063338 accepted/tizen/wearable/20160819.063317 submit/tizen/20160817.084623 submit/tizen/20160818.060816
authorjongmyeongko <jongmyeong.ko@samsung.com>
Tue, 26 Jul 2016 12:27:14 +0000 (21:27 +0900)
committerjongmyeong ko <jongmyeong.ko@samsung.com>
Thu, 11 Aug 2016 13:56:52 +0000 (06:56 -0700)
this is for new concept to support legacy app_path
for backward compatibility.

Submit together:
        https://review.tizen.org/gerrit/#/c/81862/

Change-Id: I8fab7b52ad874e05314df5a00d17a63d9e4f786b
Signed-off-by: jongmyeongko <jongmyeong.ko@samsung.com>
19 files changed:
src/common/CMakeLists.txt
src/common/pkgdir_tool_request.cc
src/common/pkgdir_tool_request.h
src/common/security_registration.cc
src/common/shared_dirs.cc
src/common/shared_dirs.h
src/common/step/backup/step_copy_backup.cc
src/common/step/configuration/step_parse_manifest.cc
src/common/step/filesystem/step_create_globalapp_symlinks.cc [new file with mode: 0644]
src/common/step/filesystem/step_create_globalapp_symlinks.h [new file with mode: 0644]
src/common/step/filesystem/step_create_per_user_storage_directories.cc
src/common/step/filesystem/step_delta_patch.cc
src/common/step/filesystem/step_remove_files.cc
src/common/step/filesystem/step_remove_globalapp_symlinks.cc [new file with mode: 0644]
src/common/step/filesystem/step_remove_globalapp_symlinks.h [new file with mode: 0644]
src/common/step/step.h
src/common/utils/file_util.cc
src/common/utils/file_util.h
src/pkgdir_tool/pkgdir_tool.cc

index ceb14e7..a7dcc1e 100644 (file)
@@ -42,6 +42,7 @@ SET(SRCS
   step/filesystem/step_copy.cc
   step/filesystem/step_copy_storage_directories.cc
   step/filesystem/step_copy_tep.cc
+  step/filesystem/step_create_globalapp_symlinks.cc
   step/filesystem/step_create_icons.cc
   step/filesystem/step_create_per_user_storage_directories.cc
   step/filesystem/step_create_legacy_directories.cc
@@ -56,6 +57,7 @@ SET(SRCS
   step/filesystem/step_recover_external_storage.cc
   step/filesystem/step_recover_storage_directories.cc
   step/filesystem/step_remove_files.cc
+  step/filesystem/step_remove_globalapp_symlinks.cc
   step/filesystem/step_remove_icons.cc
   step/filesystem/step_remove_per_user_storage_directories.cc
   step/filesystem/step_remove_legacy_directories.cc
index 6e4ba8d..20e22db 100644 (file)
@@ -16,8 +16,8 @@ const char kDBusServiceName[] = "org.tizen.pkgdir_tool";
 const char kDBusObjectPath[] = "/org/tizen/pkgdir_tool";
 const char kDBusInterfaceName[] = "org.tizen.pkgdir_tool";
 
-bool RequestUserDirectoryOperation(const char* method,
-    const std::string& pkgid) {
+bool DBusRequestForDirectoryOperation(const char* method,
+    GVariant* parameter) {
   GError* err = nullptr;
   GDBusConnection* con = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
   if (!con || err) {
@@ -39,7 +39,7 @@ bool RequestUserDirectoryOperation(const char* method,
     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,
+      parameter, G_DBUS_CALL_FLAGS_NONE, -1, nullptr,
       &err);
   if (!r) {
     std::string err_msg;
@@ -62,6 +62,18 @@ bool RequestUserDirectoryOperation(const char* method,
   return result;
 }
 
+bool RequestUserDirectoryOperation(const char* method,
+    const std::string& pkgid) {
+  GVariant* parameter = g_variant_new("(s)", pkgid.c_str());
+  return DBusRequestForDirectoryOperation(method, parameter);
+}
+
+bool RequestUserDirectoryOperationForUser(const char* method,
+    const std::string& pkgid, uid_t uid) {
+  GVariant* parameter = g_variant_new("(si)", pkgid.c_str(), uid);
+  return DBusRequestForDirectoryOperation(method, parameter);
+}
+
 }  // namespace
 
 namespace common_installer {
@@ -108,4 +120,48 @@ bool RequestDeleteLegacyDirectories(const std::string& pkgid) {
   return true;
 }
 
+bool RequestCreateGlobalAppSymlinks(const std::string& pkgid) {
+  bool result =
+      RequestUserDirectoryOperation("CreateGlobalAppSymlinks", pkgid);
+  if (!result) {
+    LOG(INFO) << "Try to create symlinks for global app directly";
+    return CreateGlobalAppSymlinksForAllUsers(pkgid);
+  }
+  return result;
+}
+
+bool RequestCreateGlobalAppSymlinksForUser(const std::string& pkgid,
+                                           uid_t uid) {
+  bool result =
+      RequestUserDirectoryOperationForUser("CreateGlobalAppSymlinksForUser",
+                                     pkgid, uid);
+  if (!result) {
+    LOG(INFO) << "Try to create symlinks for global app directly";
+    return CreateGlobalAppSymlinksForUser(pkgid, uid);
+  }
+  return result;
+}
+
+bool RequestDeleteGlobalAppSymlinks(const std::string& pkgid) {
+  bool result =
+      RequestUserDirectoryOperation("DeleteGlobalAppSymlinks", pkgid);
+  if (!result) {
+    LOG(INFO) << "Try to delete symlinks for global app directly";
+    return DeleteGlobalAppSymlinksForAllUsers(pkgid);
+  }
+  return result;
+}
+
+bool RequestDeleteGlobalAppSymlinksForUser(const std::string& pkgid,
+                                           uid_t uid) {
+  bool result =
+      RequestUserDirectoryOperationForUser("DeleteGlobalAppSymlinksForUser",
+                                     pkgid, uid);
+  if (!result) {
+    LOG(INFO) << "Try to delete symlinks for global app directly";
+    return DeleteGlobalAppSymlinksForUser(pkgid, uid);
+  }
+  return result;
+}
+
 }  // namespace common_installer
index 73e4fdf..5dba779 100644 (file)
@@ -71,6 +71,44 @@ bool RequestCreateLegacyDirectories(const std::string& pkgid);
  */
 bool RequestDeleteLegacyDirectories(const std::string& pkgid);
 
+/**
+ * \brief Request to create symlinks of global app for all users
+ *
+ * \param pkgid package id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestCreateGlobalAppSymlinks(const std::string& pkgid);
+
+/**
+ * \brief Request to create symlinks of global app for user
+ *
+ * \param pkgid package id
+ * \param uid user id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestCreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid);
+
+/**
+ * \brief Request to delete symlinks of global app for all users
+ *
+ * \param pkgid package id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestDeleteGlobalAppSymlinks(const std::string& pkgid);
+
+/**
+ * \brief Request to delete symlinks of global app for user
+ *
+ * \param pkgid package id
+ * \param uid user id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestDeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid);
+
 }  // namespace common_installer
 
 #endif  // COMMON_PKGDIR_TOOL_REQUEST_H_
index 2e0ad79..1e66eeb 100644 (file)
@@ -134,7 +134,7 @@ bool PrepareRequest(const std::string& app_id, const std::string& pkg_id,
     for (auto& policy : kSecurityPolicies) {
       bf::path subpath = path / policy.first;
       if (bf::exists(subpath)) {
-        if (bf::is_symlink(subpath)) {
+        if (bf::is_symlink(symlink_status(subpath))) {
           LOG(DEBUG) << "Path " << subpath << " is a symlink."
                      << "Path will not be registered";
           continue;
@@ -205,7 +205,7 @@ bool PreparePathRequest(const std::string& pkg_id,
   for (auto& policy : kSecurityPolicies) {
     bf::path subpath = path / policy.first;
     if (bf::exists(subpath)) {
-      if (bf::is_symlink(subpath)) {
+      if (bf::is_symlink(symlink_status(subpath))) {
         LOG(DEBUG) << "Path " << subpath << " is a symlink."
                    << "Path will not be registered";
         continue;
index ec4c6f9..2c0c364 100644 (file)
@@ -62,24 +62,25 @@ const std::vector<const char*> kEntries = {
   {"data/"},
   {"shared/"},
 };
+const std::vector<const char*> kReadOnlyEntries = {
+  {"bin"},
+  {"lib"},
+  {"res"},
+  {"shared/res"},
+};
 
+const char kSharedResDir[] = "shared/res";
 const char kSharedDataDir[] = "shared/data";
 const char kSharedTrustedDir[] = "shared/trusted";
 const char kSkelAppDir[] = "/etc/skel/apps_rw";
-const char kLegacyAppDir[] = "/opt/usr/apps";
 const char kExternalStoragePrivilege[] =
     "http://tizen.org/privilege/externalstorage.appdata";
+
 const int32_t kPWBufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
 const int32_t kGRBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
 
-bool SetOwnerAndPermissions(const bf::path& subpath, uid_t uid,
-                            gid_t gid, bf::perms perms) {
+bool SetFileOwner(const bf::path& subpath, uid_t uid, gid_t gid) {
   bs::error_code error;
-  bf::permissions(subpath, perms, error);
-  if (error) {
-    LOG(ERROR) << "Failed to set permissions for: " << subpath;
-    return false;
-  }
   int fd = open(subpath.c_str(), O_RDONLY);
   if (fd < 0) {
     LOG(ERROR) << "Can't open directory : " << subpath;
@@ -94,30 +95,39 @@ bool SetOwnerAndPermissions(const bf::path& subpath, uid_t uid,
   return true;
 }
 
-bool SetPackageDirectoryOwnerAndPermissions(const bf::path& subpath, uid_t uid,
-                                            gid_t gid) {
+bool SetOwnerAndPermissions(const bf::path& subpath, uid_t uid,
+                            gid_t gid, bf::perms perms) {
   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);
+  if (error) {
+    LOG(ERROR) << "Failed to set permissions for: " << subpath;
+    return false;
+  }
 
-  return SetOwnerAndPermissions(subpath, uid, gid, perms);
+  if (!SetFileOwner(subpath, uid, gid)) {
+    return false;
+  }
+  return true;
 }
 
-bool SetLegacyDirectoryOwnerAndPermissions(const bf::path& subpath) {
+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 |
-                    bf::others_read;
-  if (bf::is_directory(subpath))
+                    bf::group_read;
+  // symlink will be skipped
+  if (bf::is_symlink(symlink_status(subpath)))
+    return true;
+
+  // non directory will be skipped
+  bool result = true;
+  if (bf::is_directory(subpath)) {
     perms |= bf::owner_exe | bf::group_exe | bf::others_exe;
+    result = SetOwnerAndPermissions(subpath, uid, gid, perms);
+  }
 
-  return SetOwnerAndPermissions(subpath, GLOBAL_USER,
-                                tzplatform_getgid(TZ_SYS_GLOBALAPP_USER),
-                                perms);
+  return result;
 }
 
 bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
@@ -245,6 +255,91 @@ user_list GetUserList() {
   return list;
 }
 
+bool CreateSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
+  std::vector<char*> rofiles;
+  for (auto& entry : kReadOnlyEntries)
+    rofiles.push_back(strdup(entry));
+
+  for (bf::directory_iterator file(src_dir);
+      file != bf::directory_iterator();
+      ++file) {
+    if (bf::is_regular_file(file->path())) {
+      bf::path current(file->path());
+      bf::path file_name = current.filename();
+      LOG(DEBUG) << "file_name: " << file_name;
+      rofiles.push_back(strdup(file_name.c_str()));
+    }
+  }
+
+  bs::error_code error;
+  for (auto& entry : rofiles) {
+    bf::path src_path = src_dir / entry;
+    bf::path dst_path = dst_dir / entry;
+    free(const_cast<char*>(entry));
+    if (!bf::exists(src_path)) {
+      // check if symlink for .mmc/bin,lib,res, then do not skip
+      if (!bf::is_symlink(symlink_status(src_path))) {
+        LOG(ERROR) << "src_path not exist : " << src_path;
+        continue;
+      }
+    }
+    if (bf::exists(dst_path)) {
+      LOG(WARNING) << "dst_path exist, skip : " << dst_path;
+      continue;
+    }
+    bf::create_symlink(src_path, dst_path, error);
+    if (error) {
+      LOG(ERROR) << "Symlink creation failure src_path: " << src_path
+                 << " dst_path: " << dst_path;
+      LOG(ERROR) << "error: " << error.message();
+      return false;
+    }
+  }
+  return true;
+}
+
+bool DeleteSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
+  bs::error_code error;
+  for (bf::directory_iterator file(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);
+        LOG(DEBUG) << "removed: " << current;
+        if (error) {
+          LOG(ERROR) << "Symlink deletion failure for: " << current;
+          LOG(ERROR) << "error: " << error.message();
+          return false;
+        }
+      } else {
+        LOG(WARNING) << "Parent is empty or not equal to src, parenet: ("
+                   << parent << ")";
+      }
+    }
+  }
+  bf::path shared_res = dst_dir / kSharedResDir;
+  if (bf::is_symlink(symlink_status(shared_res))) {
+      bf::remove(shared_res, error);
+      if (error) {
+          LOG(ERROR) << "Symlink deletion failure for: " << shared_res;
+          LOG(ERROR) << "error: " << error.message();
+          return false;
+      }
+  }
+  return true;
+}
+
 }  // namespace
 
 namespace common_installer {
@@ -379,7 +474,7 @@ bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
 
 bool CreateSkelDirectories(const std::string& pkgid,
                            const std::string& api_version,
-                           bool trusted) {
+                           bool trusted, bool is_preload) {
   bf::path path = bf::path(kSkelAppDir) / pkgid;
   LOG(DEBUG) << "Creating directories in: " << path;
 
@@ -387,7 +482,6 @@ bool CreateSkelDirectories(const std::string& pkgid,
 
   bs::error_code error;
   bf::create_directories(path, error);
-
   if (error) {
     LOG(ERROR) << "Failed to create directory: " << path;
     return false;
@@ -416,7 +510,13 @@ bool CreateSkelDirectories(const std::string& pkgid,
     return false;
   }
 
-  return true;
+  bool result = true;
+  if (!is_preload) {
+    bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+    result = CreateSymlinkFiles(src_dir, path);
+  }
+
+  return result;
 }
 
 
@@ -465,19 +565,20 @@ bool DeleteUserExternalDirectories(const std::string& pkgid) {
 bool CopyUserDirectories(const std::string& pkgid) {
   user_list list = GetUserList();
   for (auto l : list) {
-    LOG(DEBUG) << "Copying directories for uid: " << std::get<0>(l);
+    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(kSkelAppDir) / pkgid;
     bf::path dst = apps_rw / pkgid;
-    if (!ci::CopyDir(src, dst))
+    if (!ci::CopyDir(src, dst, FSFlag::FS_NONE, true))
       continue;
-    if (!SetPackageDirectoryOwnerAndPermissions(dst, std::get<0>(l),
-        std::get<1>(l)))
+    gid_t gid = std::get<1>(l);
+    if (!SetPackageDirectoryOwnerAndPermissions(dst, uid, gid))
       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)))
+          uid, gid))
         return false;
     }
     std::string error_message;
@@ -491,77 +592,93 @@ bool CopyUserDirectories(const std::string& pkgid) {
   return true;
 }
 
-bool CreateLegacyDirectories(const std::string& pkgid) {
-  // create lagcay directories for backward compatibility
-  bs::error_code error;
-  bf::path path = bf::path(kLegacyAppDir) / pkgid;
-  bf::create_directories(path, error);
-  if (error && !bf::exists(path)) {
-    LOG(ERROR) << "Failed to create directory: " << path;
+bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
+  bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+  if (!bf::exists(src_dir)) {
+    LOG(ERROR) << "src_dir not exists";
     return false;
   }
 
-  std::vector<const char*> dirs(kEntries);
-  dirs.push_back(kSharedTrustedDir);
-  dirs.push_back(kSharedDataDir);
-  for (auto& entry : dirs) {
-    bf::path subpath = path / entry;
-    bf::create_directories(subpath, error);
-    if (error && !bf::exists(subpath)) {
-      LOG(ERROR) << "Failed to create directory: " << subpath;
-      return false;
-    }
-    if (!SetLegacyDirectoryOwnerAndPermissions(subpath)) {
-      LOG(ERROR) << "Failed to set permission: " << subpath;
-      return false;
+  bool result = true;
+  user_list list = GetUserList();
+  for (auto l : list) {
+    uid_t uid = std::get<0>(l);
+    LOG(DEBUG) << "Creating symlinks for uid: " << uid;
+    // check installed user private app.
+    if (QueryIsPackageInstalled(pkgid, uid))
+      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;
     }
+    result = CreateSymlinkFiles(src_dir, dst_dir);
   }
+  return result;
+}
 
-  std::string error_message;
-  if (!RegisterSecurityContextForPath(pkgid, path, GLOBAL_USER,
-                                      false, &error_message)) {
-    LOG(ERROR) << "Failed to register security context for path: " << path
-               << ", error_message: " << error_message;
+bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
+  bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+  if (!bf::exists(src_dir)) {
+    LOG(ERROR) << "src_dir not exists";
     return false;
   }
 
-  return true;
+  tzplatform_set_user(uid);
+  bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
+  tzplatform_reset_user();
+  if (!bf::exists(dst_dir)) {
+    LOG(WARNING) << "dst_dir not exists";
+    return true;
+  }
+  bool result = CreateSymlinkFiles(src_dir, dst_dir);
+
+  return result;
 }
 
-bool DeleteLegacyDirectories(uid_t uid, const std::string& pkgid) {
-  bool del_flag = true;
-  uid_t chk_uid;
+bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
+  bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+  if (!bf::exists(src_dir)) {
+    LOG(ERROR) << "src_dir not exists";
+    return false;
+  }
 
+  bool result = true;
   user_list list = GetUserList();
-  if (list.empty())
-    return true;
   for (auto l : list) {
-    chk_uid = std::get<0>(l);
-    if (chk_uid == uid)
+    uid_t uid = std::get<0>(l);
+    LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
+    // check installed user private app.
+    if (QueryIsPackageInstalled(pkgid, uid))
+      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;
-    LOG(DEBUG) << "Check package existence for uid: " << chk_uid;
-    if (QueryIsPackageInstalled(pkgid, chk_uid)) {
-      LOG(DEBUG) << "Package: " << pkgid << " for uid: " << chk_uid
-                 << " still exists.";
-      del_flag = false;
-      break;;
     }
+    result = DeleteSymlinkFiles(src_dir, dst_dir);
   }
+  return result;
+}
 
-  if (del_flag && uid != GLOBAL_USER) {
-    if (QueryIsPackageInstalled(pkgid, GLOBAL_USER)) {
-      LOG(DEBUG) << "Package: " << pkgid << " for uid: " << GLOBAL_USER
-                 << " still exists.";
-      del_flag = false;
-    }
+bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
+  bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+  if (!bf::exists(src_dir)) {
+    LOG(ERROR) << "src_dir not exists";
+    return false;
   }
 
-  if (del_flag) {
-    LOG(DEBUG) << "Delete legacy directories for package: " << pkgid;
-    DeleteDirectories(bf::path(kLegacyAppDir), pkgid);
+  tzplatform_set_user(uid);
+  bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
+  tzplatform_reset_user();
+  if (!bf::exists(dst_dir)) {
+    LOG(WARNING) << "dst_dir not exists";
+    return true;
   }
-
-  return true;
+  bool result = DeleteSymlinkFiles(src_dir, dst_dir);
+  return result;
 }
 
 }  // namespace common_installer
index e309d4a..a5ed0cd 100644 (file)
@@ -69,13 +69,14 @@ bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid);
  * \param pkgid package id
  * \param api_version package api version
  * \param trusted signed package flag
+ * \param is_preload preload flag
  *
  * \return bool true if succeed, false otherwise
  *
  */
 bool CreateSkelDirectories(const std::string& pkgid,
                            const std::string& api_version,
-                           bool trusted);
+                           bool trusted, bool is_preload);
 
 /**
  * \brief Performs deletion of directories
@@ -124,25 +125,46 @@ std::string GetDirectoryPathForInternalStorage();
 std::string GetDirectoryPathForExternalStorage();
 
 /**
- * \brief Create Legacy directories
+ * \brief Create symlinks for read-only files of global app for all users.
  *
+ * \param pkgid package id
+ *
+ * \return true if succeed, false otherwise
+ *
+ */
+bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid);
+
+/**
+ * \brief Create symlinks for read-only files of global app for user.
+ *
+ * \param pkgid package id
  * \param uid user id
+ *
+ * \return true if succeed, false otherwise
+ *
+ */
+bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid);
+
+/**
+ * \brief Delete symlinks for read-only files of global app for all users.
+ *
  * \param pkgid package id
  *
  * \return true if succeed, false otherwise
  *
  */
-bool CreateLegacyDirectories(const std::string& pkgid);
+bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid);
 
 /**
- * \brief Delete Legacy directories
+ * \brief Delete symlinks for read-only files of global app for user.
  *
  * \param pkgid package id
+ * \param uid user id
  *
  * \return true if succeed, false otherwise
  *
  */
-bool DeleteLegacyDirectories(uid_t uid, const std::string& pkgid);
+bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid);
 
 }  // namespace common_installer
 
index 9bb2ce1..922c5d1 100644 (file)
@@ -144,7 +144,7 @@ bool StepCopyBackup::MoveMountPointContent(const boost::filesystem::path& from,
         LOG(ERROR) << "Fail to backup package directory of: " << iter->path();
         return false;
       }
-    } else if (bf::is_symlink(iter->path())) {
+    } else if (bf::is_symlink(symlink_status(iter->path()))) {
       bs::error_code error;
       bf::copy_symlink(iter->path(), to / iter->path().filename(), error);
       if (error) {
index e86931c..5d24cd1 100644 (file)
@@ -826,9 +826,6 @@ Step::Status StepParseManifest::process() {
     return Step::Status::PARSE_ERROR;
   }
 
-  // TODO(jongmyeongko): check package features...
-  // Implementation of this need more consideration (offline mode and store app)
-
   if (manifest_location_ == ManifestLocation::INSTALLED) {
     // recovery of tep value for installed package
     std::string old_tep =
diff --git a/src/common/step/filesystem/step_create_globalapp_symlinks.cc b/src/common/step/filesystem/step_create_globalapp_symlinks.cc
new file mode 100644 (file)
index 0000000..0f535fb
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/step/filesystem/step_create_globalapp_symlinks.h"
+
+#include <string>
+
+#include "common/pkgdir_tool_request.h"
+#include "common/shared_dirs.h"
+#include "common/pkgmgr_query.h"
+
+namespace common_installer {
+namespace filesystem {
+
+common_installer::Step::Status StepCreateGlobalAppSymlinks::process() {
+  if (context_->is_preload_request.get())
+    return Step::Status::OK;
+  std::string package_id = context_->pkgid.get();
+
+  if (context_->request_type.get() == RequestType::Uninstall) {
+    if ((context_->request_mode.get() == RequestMode::USER) &&
+        QueryIsPackageInstalled(context_->pkgid.get(), GLOBAL_USER)) {
+      LOG(INFO) << "Creating globalapp symlinks for current user, package: "
+              << package_id;
+      if (!RequestCreateGlobalAppSymlinksForUser(package_id,
+                                        context_->uid.get())) {
+        LOG(ERROR) << "Failed to create globalapp symlinks";
+        return Status::GLOBALSYMLINK_ERROR;
+      }
+    }
+  } else {
+    if (context_->request_mode.get() == RequestMode::GLOBAL) {
+      LOG(INFO) << "Creating globalapp symlinks for all user, package: "
+                << package_id;
+      if (!RequestCreateGlobalAppSymlinks(package_id)) {
+        LOG(ERROR) << "Failed to create globalapp symlinks";
+        return Status::GLOBALSYMLINK_ERROR;
+      }
+    }
+  }
+
+  return Status::OK;
+}
+
+}  // namespace filesystem
+}  // namespace common_installer
diff --git a/src/common/step/filesystem/step_create_globalapp_symlinks.h b/src/common/step/filesystem/step_create_globalapp_symlinks.h
new file mode 100644 (file)
index 0000000..46ba642
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_STEP_FILESYSTEM_STEP_CREATE_GLOBALAPP_SYMLINKS_H_
+#define COMMON_STEP_FILESYSTEM_STEP_CREATE_GLOBALAPP_SYMLINKS_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include "common/step/step.h"
+
+namespace common_installer {
+namespace filesystem {
+
+/**
+ * \brief Installation.
+ *        Responsible for creating symlinks for read-only files of globalapp
+ *        for backward compatibility. (wgt/tpk)
+ *
+ * * process method implements creation of symlinks under RW app_root per user.
+ *
+ * * Other methods are empty.
+ */
+class StepCreateGlobalAppSymlinks : public common_installer::Step {
+ public:
+  using Step::Step;
+
+  Status process() override;
+  Status clean() override { return Status::OK; }
+  Status undo() override { return Status::OK; }
+  Status precheck() override { return Status::OK; }
+
+  STEP_NAME(CreateGlobalAppSymlinks)
+};
+
+}  // namespace filesystem
+}  // namespace common_installer
+
+#endif  // COMMON_STEP_FILESYSTEM_STEP_CREATE_GLOBALAPP_SYMLINKS_H_
index 6cd8ccf..accbb83 100644 (file)
@@ -31,7 +31,7 @@ common_installer::Step::Status StepCreatePerUserStorageDirectories::process() {
     trusted = true;
 
   if (!common_installer::CreateSkelDirectories(package_id,
-      str_ver, trusted)) {
+      str_ver, trusted, context_->is_preload_request.get())) {
     LOG(ERROR) << "Failed to create skel dirs";
     return Status::APP_DIR_ERROR;
   }
index 74cd25c..b29325a 100644 (file)
@@ -54,7 +54,7 @@ bool ValidateDeltaInfo(const delta::DeltaInfo& info) {
 void RemoveBinarySymlinks(const bf::path& dir) {
   for (bf::directory_iterator iter(dir / kBinaryDir);
       iter != bf::directory_iterator(); ++iter) {
-    if (bf::is_symlink(iter->path())) {
+    if (bf::is_symlink(symlink_status(iter->path()))) {
       // FIXME: note that this assumes that it is not possible to create
       // explicitly symlinks in bin/ directory pointing to whatever
       bs::error_code error;
index 56438ce..8455c7f 100644 (file)
@@ -17,7 +17,7 @@ namespace bs = boost::system;
 namespace bf = boost::filesystem;
 
 namespace {
-const char kSharedRes[] = "shared/res";
+
 bool SkipDirectoryIfGlobal(const bf::path& path) {
   static const std::vector<std::string> dirs_to_ignore = {
     {"cache"},
@@ -27,6 +27,7 @@ bool SkipDirectoryIfGlobal(const bf::path& path) {
   return std::find(dirs_to_ignore.begin(), dirs_to_ignore.end(), path) !=
       dirs_to_ignore.end();
 }
+
 }  // namespace
 
 
@@ -60,13 +61,13 @@ Step::Status StepRemoveFiles::process() {
   if (context_->external_storage)
     context_->external_storage->Commit();
 
-  // If global package, then some RW directories won't be removed here,
-  // instead, following StepRemoveLegacyDirectories will check and remove them.
-  if (QueryIsPackageInstalled(context_->pkgid.get(), GLOBAL_USER) ||
-      context_->uid.get() == GLOBAL_USER) {
+  if (QueryIsPackageInstalled(context_->pkgid.get(), GLOBAL_USER)) {
     for (bf::directory_iterator itr(pkg_path); itr != bf::directory_iterator();
         ++itr) {
-      if (bf::is_directory(itr->status())) {
+      if (bf::is_symlink(symlink_status(itr->path()))) {
+        // for removing symlink to .mmc/bin,lib,res
+        bf::remove_all(itr->path(), error);
+      } else if (bf::is_directory(itr->status())) {
         if (SkipDirectoryIfGlobal(itr->path().leaf())) {
           LOG(DEBUG) << "Skipping remove dir:" << itr->path().c_str();
           continue;
@@ -79,9 +80,6 @@ Step::Status StepRemoveFiles::process() {
         bf::remove_all(itr->path(), error);
       }
     }
-    // The shared/res will be removed if it exists.
-    bf::path shared_res_path = pkg_path / kSharedRes;
-    bf::remove_all(shared_res_path, error);
   } else {
     bf::remove_all(pkg_path, error);
     if (error) {
diff --git a/src/common/step/filesystem/step_remove_globalapp_symlinks.cc b/src/common/step/filesystem/step_remove_globalapp_symlinks.cc
new file mode 100644 (file)
index 0000000..6626b65
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/step/filesystem/step_remove_globalapp_symlinks.h"
+
+#include <string>
+
+#include "common/installer_context.h"
+#include "common/pkgdir_tool_request.h"
+#include "common/pkgmgr_query.h"
+
+namespace common_installer {
+namespace filesystem {
+
+Step::Status StepRemoveGlobalAppSymlinks::process() {
+  if (context_->is_preload_request.get())
+    return Step::Status::OK;
+
+  if (!QueryIsPackageInstalled(context_->pkgid.get(), GLOBAL_USER))
+    return Step::Status::OK;
+
+  std::string package_id = context_->pkgid.get();
+
+  if (context_->request_type.get() == RequestType::Uninstall) {
+    if (context_->request_mode.get() == RequestMode::GLOBAL) {
+      LOG(INFO) << "Deleting globalapp symlinks for all user, package: "
+                << package_id;
+      if (!RequestDeleteGlobalAppSymlinks(package_id)) {
+        LOG(ERROR) << "Failed to delete globalapp symlinks";
+        return Status::GLOBALSYMLINK_ERROR;
+      }
+    }
+  } else {
+    LOG(INFO) << "Deleting globalapp symlinks for current user, package: "
+                << package_id;
+    if (!RequestDeleteGlobalAppSymlinksForUser(package_id,
+                                        context_->uid.get())) {
+      LOG(ERROR) << "Failed to delete globalapp symlinks";
+      return Status::GLOBALSYMLINK_ERROR;
+    }
+  }
+
+  return Step::Status::OK;
+}
+
+}  // namespace filesystem
+}  // namespace common_installer
+
diff --git a/src/common/step/filesystem/step_remove_globalapp_symlinks.h b/src/common/step/filesystem/step_remove_globalapp_symlinks.h
new file mode 100644 (file)
index 0000000..d870382
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_STEP_FILESYSTEM_STEP_REMOVE_GLOBALAPP_SYMLINKS_H_
+#define COMMON_STEP_FILESYSTEM_STEP_REMOVE_GLOBALAPP_SYMLINKS_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include "common/step/step.h"
+
+namespace common_installer {
+namespace filesystem {
+
+/**
+ * \brief Uninstallation.
+ *        Responsible for removing symlink files for read-only files of globalapp
+ *        for backward compatibility. (wgt/tpk)
+ *
+ * * process method implements removal of symlinks under RW app_root per user.
+ *
+ * * Other methods are empty.
+ *
+ */
+
+class StepRemoveGlobalAppSymlinks : public common_installer::Step {
+ public:
+  using Step::Step;
+
+  Status process() override;
+  Status clean() override { return Status::OK; }
+  Status undo() override { return Status::OK; }
+  Status precheck() override { return Status::OK; }
+
+  STEP_NAME(RemoveGlobalAppSymlinks)
+};
+
+}  // namespace filesystem
+}  // namespace common_installer
+
+#endif  // COMMON_STEP_FILESYSTEM_STEP_REMOVE_GLOBALAPP_SYMLINKS_H_
index 960a351..ffe9dcd 100644 (file)
@@ -50,6 +50,7 @@ class Step {
  public:
   /** Possible code returned by process, undo, clean, precheck methods. */
   enum class Status {
+    GLOBALSYMLINK_ERROR = -26,  // TODO(jongmyeong.ko)
     GRANT_PERMISSION_ERROR = PKGCMD_ERRCODE_GRANT_PERMISSION_ERROR,
     IMAGE_ERROR = PKGCMD_ERRCODE_IMAGE_ERROR,
     UNZIP_ERROR = PKGCMD_ERRCODE_UNZIP_ERROR,
index ac01a16..3551b50 100644 (file)
@@ -119,7 +119,8 @@ bool SetDirPermissions(const boost::filesystem::path& path,
   return true;
 }
 
-bool CopyDir(const bf::path& src, const bf::path& dst, FSFlag flags) {
+bool CopyDir(const bf::path& src, const bf::path& dst,
+             FSFlag flags, bool skip_symlink) {
   try {
     // Check whether the function call is valid
     if (!bf::exists(src) || !bf::is_directory(src)) {
@@ -152,15 +153,18 @@ bool CopyDir(const bf::path& src, const bf::path& dst, FSFlag flags) {
     try {
       bf::path current(file->path());
       bf::path target = dst / current.filename();
-      if (bf::is_directory(current)) {
-        // Found directory: Recursion
-        if (!CopyDir(current, target, flags)) {
-          return false;
-        }
-      } else if (bf::is_symlink(current)) {
+
+      if (bf::is_symlink(symlink_status(current))) {
+        if (skip_symlink)
+          continue;
         if ((flags & FS_MERGE_DIRECTORIES) && bf::exists(target))
           continue;
         bf::copy_symlink(current, target);
+      } else if (bf::is_directory(current)) {
+        // Found directory: Recursion
+        if (!CopyDir(current, target, flags, skip_symlink)) {
+          return false;
+        }
       } else {
         if ((flags & FS_MERGE_DIRECTORIES) && bf::exists(target))
           continue;
@@ -195,7 +199,7 @@ bool MoveDir(const bf::path& src, const bf::path& dst, FSFlag flags) {
   bf::rename(src, dst, error);
   if (error) {
     LOG(WARNING) << "Cannot move directory: " << src << ". Will copy/remove...";
-    if (!CopyDir(src, dst, flags)) {
+    if (!CopyDir(src, dst, flags, false)) {
       LOG(ERROR) << "Cannot copy directory: " << src;
       return false;
     }
index 3ee984b..83cd81e 100644 (file)
@@ -17,7 +17,8 @@ enum FSFlag {
 bool CreateDir(const boost::filesystem::path& path);
 
 bool CopyDir(const boost::filesystem::path& src,
-             const boost::filesystem::path& dst, FSFlag flags = FS_NONE);
+             const boost::filesystem::path& dst,
+             FSFlag flags = FS_NONE, bool skip_symlink = false);
 
 bool CopyFile(const boost::filesystem::path& src,
              const boost::filesystem::path& dst);
index b24d827..d5cd430 100644 (file)
@@ -33,15 +33,25 @@ const char kDBusInstropectionXml[] =
   "      <arg type='s' name='pkgid' direction='in'/>"
   "      <arg type='b' name='result' direction='out'/>"
   "    </method>"
-  "    <method name='CreateLegacyDirs'>"
+  "    <method name='CreateExternalDirsForAllPkgs'>"
+  "      <arg type='b' name='result' direction='out'/>"
+  "    </method>"
+  "    <method name='CreateGlobalAppSymlinks'>"
   "      <arg type='s' name='pkgid' direction='in'/>"
   "      <arg type='b' name='result' direction='out'/>"
   "    </method>"
-  "    <method name='DeleteLegacyDirs'>"
+  "    <method name='DeleteGlobalAppSymlinks'>"
   "      <arg type='s' name='pkgid' direction='in'/>"
   "      <arg type='b' name='result' direction='out'/>"
   "    </method>"
-  "    <method name='CreateExternalDirsForAllPkgs'>"
+  "    <method name='CreateGlobalAppSymlinksForUser'>"
+  "      <arg type='s' name='pkgid' direction='in'/>"
+  "      <arg type='i' name='uid' direction='in'/>"
+  "      <arg type='b' name='result' direction='out'/>"
+  "    </method>"
+  "    <method name='DeleteGlobalAppSymlinksForUser'>"
+  "      <arg type='s' name='pkgid' direction='in'/>"
+  "      <arg type='i' name='uid' direction='in'/>"
   "      <arg type='b' name='result' direction='out'/>"
   "    </method>"
   "  </interface>"
@@ -66,7 +76,6 @@ class PkgdirToolService {
       gpointer user_data);
   void OnBusAcquired(GDBusConnection* connection, const gchar* name,
       gpointer user_data);
-  int GetSenderUnixId(GDBusConnection *connection, const gchar* sender);
 
   GDBusNodeInfo* node_info_;
   guint owner_id_;
@@ -133,48 +142,12 @@ void PkgdirToolService::RenewTimeout(int ms) {
       this);
 }
 
-int PkgdirToolService::GetSenderUnixId(GDBusConnection* connection,
-    const gchar* sender) {
-  int uid = -1;
-
-  GDBusMessage* msg = nullptr;
-  msg = g_dbus_message_new_method_call("org.freedesktop.DBus",
-                                       "/org/freedesktop/DBus",
-                                       "org.freedesktop.DBus",
-                                       "GetConnectionUnixUser");
-  if (!msg) {
-    LOG(ERROR) << "Failed to setup dbus message";
-    return -1;
-  }
-  g_dbus_message_set_body(msg, g_variant_new("(s)", sender));
-
-  GError* err = nullptr;
-  GDBusMessage* reply = nullptr;
-  reply = g_dbus_connection_send_message_with_reply_sync(connection, msg,
-      G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, nullptr, nullptr, &err);
-  if (!reply) {
-    LOG(ERROR) << "Failed to send dbus message";
-    if (err) {
-      LOG(ERROR) << "error message: " <<  err->message;
-      g_error_free(err);
-    }
-    g_object_unref(msg);
-    return -1;
-  }
-
-  GVariant* body = g_dbus_message_get_body(reply);
-  g_variant_get(body, "(u)", &uid);
-
-  g_object_unref(msg);
-  g_object_unref(reply);
-
-  return uid;
-}
-
 void PkgdirToolService::HandleMethodCall(GDBusConnection* connection,
     const gchar* sender, const gchar* object_path, const gchar* interface_name,
     const gchar* method_name, GVariant* parameters,
     GDBusMethodInvocation* invocation, gpointer user_data) {
+  UNUSED(connection);
+  UNUSED(sender);
   UNUSED(object_path);
   UNUSED(interface_name);
   UNUSED(user_data);
@@ -194,19 +167,22 @@ void PkgdirToolService::HandleMethodCall(GDBusConnection* connection,
   } else if (g_strcmp0(method_name, "DeleteExternalDirs") == 0) {
     g_variant_get(parameters, "(&s)", &val);
     r = ci::PerformExternalDirectoryDeletionForAllUsers(std::string(val));
-  } else if (g_strcmp0(method_name, "CreateLegacyDirs") == 0) {
-    g_variant_get(parameters, "(&s)", &val);
-    r = ci::CreateLegacyDirectories(std::string(val));
-  } else if (g_strcmp0(method_name, "DeleteLegacyDirs") == 0) {
-    g_variant_get(parameters, "(&s)", &val);
-    int sender_uid = GetSenderUnixId(connection, sender);
-    if (sender_uid < 0) {
-      LOG(ERROR) << "Failed to get sender_uid: " << sender_uid;
-    } else {
-      r = ci::DeleteLegacyDirectories((uid_t)sender_uid, std::string(val));
-    }
   } else if (g_strcmp0(method_name, "CreateExternalDirsForAllPkgs") == 0) {
     r = ci::PerformExternalDirectoryCreationForAllPkgs();
+  } else if (g_strcmp0(method_name, "CreateGlobalAppSymlinks") == 0) {
+    g_variant_get(parameters, "(&s)", &val);
+    r = ci::CreateGlobalAppSymlinksForAllUsers(std::string(val));
+  } else if (g_strcmp0(method_name, "DeleteGlobalAppSymlinks") == 0) {
+    g_variant_get(parameters, "(&s)", &val);
+    r = ci::DeleteGlobalAppSymlinksForAllUsers(std::string(val));
+  } else if (g_strcmp0(method_name, "CreateGlobalAppSymlinksForUser") == 0) {
+    uid_t uid;
+    g_variant_get(parameters, "(&si)", &val, &uid);
+    r = ci::CreateGlobalAppSymlinksForUser(std::string(val), uid);
+  } else if (g_strcmp0(method_name, "DeleteGlobalAppSymlinksForUser") == 0) {
+    uid_t uid;
+    g_variant_get(parameters, "(&si)", &val, &uid);
+    r = ci::DeleteGlobalAppSymlinksForUser(std::string(val), uid);
   } else {
     LOG(ERROR) << "Unknown method call: " << method_name;
   }