support of legacy app directories 19/80319/7
authorjongmyeongko <jongmyeong.ko@samsung.com>
Sat, 16 Jul 2016 07:31:02 +0000 (16:31 +0900)
committerjongmyeongko <jongmyeong.ko@samsung.com>
Fri, 22 Jul 2016 08:25:46 +0000 (17:25 +0900)
dependent change:
https://review.tizen.org/gerrit/#/c/80279/

Change-Id: I418d9be1ded705e8fc2af286fb70adb2d594e277
Signed-off-by: jongmyeongko <jongmyeong.ko@samsung.com>
12 files changed:
src/common/CMakeLists.txt
src/common/pkgdir_tool_request.cc
src/common/pkgdir_tool_request.h
src/common/shared_dirs.cc
src/common/shared_dirs.h
src/common/step/filesystem/step_create_legacy_directories.cc [new file with mode: 0644]
src/common/step/filesystem/step_create_legacy_directories.h [new file with mode: 0644]
src/common/step/filesystem/step_remove_files.cc
src/common/step/filesystem/step_remove_legacy_directories.cc [new file with mode: 0644]
src/common/step/filesystem/step_remove_legacy_directories.h [new file with mode: 0644]
src/pkgdir_tool/org.tizen.pkgdir_tool.conf
src/pkgdir_tool/pkgdir_tool.cc

index d0cfdbb..98b3959 100644 (file)
@@ -41,6 +41,7 @@ SET(SRCS
   step/filesystem/step_copy_tep.cc
   step/filesystem/step_create_icons.cc
   step/filesystem/step_create_per_user_storage_directories.cc
+  step/filesystem/step_create_legacy_directories.cc
   step/filesystem/step_create_storage_directories.cc
   step/filesystem/step_delta_patch.cc
   step/filesystem/step_move_installed_storage.cc
@@ -52,6 +53,7 @@ SET(SRCS
   step/filesystem/step_remove_files.cc
   step/filesystem/step_remove_icons.cc
   step/filesystem/step_remove_per_user_storage_directories.cc
+  step/filesystem/step_remove_legacy_directories.cc
   step/filesystem/step_remove_temporary_directory.cc
   step/filesystem/step_remove_tep.cc
   step/filesystem/step_remove_zip_image.cc
index c13ced5..6e4ba8d 100644 (file)
@@ -98,4 +98,14 @@ bool RequestDeleteExternalDirectories(const std::string& pkgid) {
   return true;
 }
 
+bool RequestCreateLegacyDirectories(const std::string& pkgid) {
+  RequestUserDirectoryOperation("CreateLegacyDirs", pkgid);
+  return true;
+}
+
+bool RequestDeleteLegacyDirectories(const std::string& pkgid) {
+  RequestUserDirectoryOperation("DeleteLegacyDirs", pkgid);
+  return true;
+}
+
 }  // namespace common_installer
index d8fcefc..73e4fdf 100644 (file)
@@ -53,6 +53,24 @@ bool RequestCreateExternalDirectories(const std::string& pkgid);
  */
 bool RequestDeleteExternalDirectories(const std::string& pkgid);
 
+/**
+ * \brief Request to create legacy directories
+ *
+ * \param pkgid package id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestCreateLegacyDirectories(const std::string& pkgid);
+
+/**
+ * \brief Request to delete legacy directories
+ *
+ * \param pkgid package id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestDeleteLegacyDirectories(const std::string& pkgid);
+
 }  // namespace common_installer
 
 #endif  // COMMON_PKGDIR_TOOL_REQUEST_H_
index a93202d..6bd239a 100644 (file)
@@ -64,8 +64,9 @@ const std::vector<const char*> kEntries = {
 };
 
 const char kSharedDataDir[] = "shared/data";
-const char kTrustedDir[] = "shared/trusted";
+const char kSharedTrustedDir[] = "shared/trusted";
 const char kSkelAppDir[] = "/etc/skel/apps_rw";
+const char kLegacyAppDir[] = "/opt/usr/apps";
 const char kPackagePattern[] = R"(^[0-9a-zA-Z_-]+(\.?[0-9a-zA-Z_-]+)*$)";
 const int32_t kPWBufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
 const int32_t kGRBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
@@ -120,7 +121,7 @@ int PkgmgrListCallback(const pkgmgrinfo_pkginfo_h handle, void *user_data) {
 ci::PkgList GetAllGlobalAppsInformation() {
   ci::PkgList pkgs;
   if (pkgmgrinfo_pkginfo_get_usr_list(&PkgmgrListCallback,
-      &pkgs, tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)) != PMINFO_R_OK) {
+      &pkgs, GLOBAL_USER) != PMINFO_R_OK) {
     LOG(ERROR) << "Failed to query global application list";
     return {};
   }
@@ -149,15 +150,9 @@ ci::PkgList GetPkgInformation(uid_t uid, const std::string& pkgid) {
   return pkgs;
 }
 
-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;
@@ -177,6 +172,32 @@ bool SetPackageDirectoryOwnerAndPermissions(const bf::path& subpath, uid_t uid,
   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;
+
+  return SetOwnerAndPermissions(subpath, uid, gid, perms);
+}
+
+bool SetLegacyDirectoryOwnerAndPermissions(const bf::path& subpath) {
+  bs::error_code error;
+  bf::perms perms = bf::owner_read |
+                    bf::owner_write |
+                    bf::group_read |
+                    bf::others_read;
+  if (bf::is_directory(subpath))
+    perms |= bf::owner_exe | bf::group_exe | bf::others_exe;
+
+  return SetOwnerAndPermissions(subpath, GLOBAL_USER,
+                                tzplatform_getgid(TZ_SYS_GLOBALAPP_USER),
+                                perms);
+}
+
 bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
                        bool trusted,
                        uid_t uid, gid_t gid, const bool set_permissions) {
@@ -189,7 +210,7 @@ bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
   bs::error_code error;
   std::vector<const char*> dirs(kEntries);
   if (trusted)
-    dirs.push_back(kTrustedDir);
+    dirs.push_back(kSharedTrustedDir);
   for (auto& entry : dirs) {
     bf::path subpath = base_dir / entry;
     bf::create_directories(subpath, error);
@@ -434,7 +455,7 @@ bool CreateSkelDirectories(const std::string& pkgid,
 
   std::vector<const char*> dirs(kEntries);
   if (trusted)
-    dirs.push_back(kTrustedDir);
+    dirs.push_back(kSharedTrustedDir);
   if (api_ver < ver30) {
     dirs.push_back(kSharedDataDir);
   }
@@ -448,8 +469,8 @@ bool CreateSkelDirectories(const std::string& pkgid,
   }
 
   std::string error_message;
-  if (!RegisterSecurityContextForPath(pkgid, path,
-      tzplatform_getuid(TZ_SYS_GLOBALAPP_USER), false, &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;
     return false;
@@ -536,4 +557,77 @@ ci::PkgList CreatePkgInformationList(uid_t uid,
       GetAllGlobalAppsInformation() : GetPkgInformation(uid, *pkgs.begin());
 }
 
+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;
+    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;
+    }
+  }
+
+  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;
+    return false;
+  }
+
+  return true;
+}
+
+bool DeleteLegacyDirectories(uid_t uid, const std::string& pkgid) {
+  bool del_flag = true;
+  uid_t chk_uid;
+
+  user_list list = GetUserList();
+  if (list.empty())
+    return true;
+  for (auto l : list) {
+    chk_uid = std::get<0>(l);
+    if (chk_uid == uid)
+      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;;
+    }
+  }
+
+  if (del_flag && uid != GLOBAL_USER) {
+    if (QueryIsPackageInstalled(pkgid, GLOBAL_USER)) {
+      LOG(DEBUG) << "Package: " << pkgid << " for uid: " << GLOBAL_USER
+                 << " still exists.";
+      del_flag = false;
+    }
+  }
+
+  if (del_flag) {
+    LOG(DEBUG) << "Delete legacy directories for package: " << pkgid;
+    DeleteDirectories(bf::path(kLegacyAppDir), pkgid);
+  }
+
+  return true;
+}
+
 }  // namespace common_installer
index 7d94de6..087f5ed 100644 (file)
@@ -166,6 +166,27 @@ std::string GetDirectoryPathForInternalStorage();
  */
 std::string GetDirectoryPathForExternalStorage();
 
+/**
+ * \brief Create Legacy directories
+ *
+ * \param uid user id
+ * \param pkgid package id
+ *
+ * \return true if succeed, false otherwise
+ *
+ */
+bool CreateLegacyDirectories(const std::string& pkgid);
+
+/**
+ * \brief Delete Legacy directories
+ *
+ * \param pkgid package id
+ *
+ * \return true if succeed, false otherwise
+ *
+ */
+bool DeleteLegacyDirectories(uid_t uid, const std::string& pkgid);
+
 }  // namespace common_installer
 
 #endif  // COMMON_SHARED_DIRS_H_
diff --git a/src/common/step/filesystem/step_create_legacy_directories.cc b/src/common/step/filesystem/step_create_legacy_directories.cc
new file mode 100644 (file)
index 0000000..7cf9435
--- /dev/null
@@ -0,0 +1,25 @@
+// 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_legacy_directories.h"
+
+#include <string>
+
+#include "common/pkgdir_tool_request.h"
+#include "common/shared_dirs.h"
+
+namespace common_installer {
+namespace filesystem {
+
+common_installer::Step::Status StepCreateLegacyDirectories::process() {
+  std::string package_id = context_->pkgid.get();
+
+  LOG(INFO) << "Creating legacy directories for package: " << package_id;
+  common_installer::RequestCreateLegacyDirectories(package_id);
+
+  return Status::OK;
+}
+
+}  // namespace filesystem
+}  // namespace common_installer
diff --git a/src/common/step/filesystem/step_create_legacy_directories.h b/src/common/step/filesystem/step_create_legacy_directories.h
new file mode 100644 (file)
index 0000000..f1b4ec1
--- /dev/null
@@ -0,0 +1,40 @@
+// 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_LEGACY_DIRECTORIES_H_
+#define COMMON_STEP_FILESYSTEM_STEP_CREATE_LEGACY_DIRECTORIES_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include "common/step/step.h"
+
+namespace common_installer {
+namespace filesystem {
+
+/**
+ * \brief Installation.
+ *        Responsible for creating RW directoires under legacy app-root
+ *        for backward compatibility. (wgt/tpk)
+ *
+ * * process method implements creation of data and shared directories
+ *   under /opt/usr/apps.
+ *
+ * * Other methods are empty.
+ */
+class StepCreateLegacyDirectories : 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(CreateLegacyDirectories)
+};
+
+}  // namespace filesystem
+}  // namespace common_installer
+
+#endif  // COMMON_STEP_FILESYSTEM_STEP_CREATE_LEGACY_DIRECTORIES_H_
index 8e235c7..56438ce 100644 (file)
@@ -17,6 +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"},
@@ -59,7 +60,10 @@ Step::Status StepRemoveFiles::process() {
   if (context_->external_storage)
     context_->external_storage->Commit();
 
-  if (QueryIsPackageInstalled(context_->pkgid.get(), GLOBAL_USER)) {
+  // 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) {
     for (bf::directory_iterator itr(pkg_path); itr != bf::directory_iterator();
         ++itr) {
       if (bf::is_directory(itr->status())) {
@@ -75,6 +79,9 @@ 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_legacy_directories.cc b/src/common/step/filesystem/step_remove_legacy_directories.cc
new file mode 100644 (file)
index 0000000..97678d9
--- /dev/null
@@ -0,0 +1,25 @@
+// 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_legacy_directories.h"
+
+#include <string>
+
+#include "common/installer_context.h"
+#include "common/pkgdir_tool_request.h"
+
+namespace common_installer {
+namespace filesystem {
+
+Step::Status StepRemoveLegacyDirectories::process() {
+  std::string package_id = context_->pkgid.get();
+
+  common_installer::RequestDeleteLegacyDirectories(package_id);
+
+  return Step::Status::OK;
+}
+
+}  // namespace filesystem
+}  // namespace common_installer
+
diff --git a/src/common/step/filesystem/step_remove_legacy_directories.h b/src/common/step/filesystem/step_remove_legacy_directories.h
new file mode 100644 (file)
index 0000000..e18ef1e
--- /dev/null
@@ -0,0 +1,42 @@
+// 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_LEGACY_DIRECTORIES_H_
+#define COMMON_STEP_FILESYSTEM_STEP_REMOVE_LEGACY_DIRECTORIES_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include "common/step/step.h"
+
+namespace common_installer {
+namespace filesystem {
+
+/**
+ * \brief Uninstallation.
+ *        Responsible for removing RW directoires under legacy app-root
+ *        (wgt/tpk)
+ *
+ * * process method implements removal of data and shared directories
+ *   under /opt/usr/apps.
+ *
+ * * Other methods are empty.
+ *
+ */
+
+class StepRemoveLegacyDirectories : 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(RemoveLegacyDirectories)
+};
+
+}  // namespace filesystem
+}  // namespace common_installer
+
+#endif  // COMMON_STEP_FILESYSTEM_STEP_REMOVE_LEGACY_DIRECTORIES_H_
index 83c616a..12f5e20 100644 (file)
@@ -5,12 +5,11 @@
 <busconfig>
   <policy user="root">
     <allow own="org.tizen.pkgdir_tool"/>
-    <allow send_destination="org.tizen.pkgdir_tool"/>
   </policy>
-  <policy user="tizenglobalapp">
-    <allow send_destination="org.tizen.pkgdir_tool"/>
+  <policy user="app_fw">
+    <allow own="org.tizen.pkgdir_tool"/>
   </policy>
   <policy context="default">
-    <deny send_destination="org.tizen.pkgdir_tool"/>
+    <check send_destination="org.tizen.pkgdir_tool" send_interface="org.tizen.pkgdir_tool" privilege="http://tizen.org/privilege/packagemanager.admin"/>
   </policy>
 </busconfig>
index 2bbc17f..d796742 100644 (file)
@@ -33,6 +33,14 @@ const char kDBusInstropectionXml[] =
   "      <arg type='s' name='pkgid' direction='in'/>"
   "      <arg type='b' name='result' direction='out'/>"
   "    </method>"
+  "    <method name='CreateLegacyDirs'>"
+  "      <arg type='s' name='pkgid' direction='in'/>"
+  "      <arg type='b' name='result' direction='out'/>"
+  "    </method>"
+  "    <method name='DeleteLegacyDirs'>"
+  "      <arg type='s' name='pkgid' direction='in'/>"
+  "      <arg type='b' name='result' direction='out'/>"
+  "    </method>"
   "  </interface>"
   "</node>";
 const char kDBusServiceName[] = "org.tizen.pkgdir_tool";
@@ -55,6 +63,7 @@ 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_;
@@ -121,19 +130,57 @@ 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);
   char* val;
   g_variant_get(parameters, "(s)", &val);
+
   bool r = false;
   LOG(INFO) << "Incomming method call: " << method_name;
+
   if (g_strcmp0(method_name, "CopyUserDirs") == 0) {
     r = ci::CopyUserDirectories(std::string(val));
   } else if (g_strcmp0(method_name, "DeleteUserDirs") == 0) {
@@ -142,6 +189,15 @@ void PkgdirToolService::HandleMethodCall(GDBusConnection* connection,
     r = ci::PerformExternalDirectoryCreationForAllUsers(std::string(val));
   } else if (g_strcmp0(method_name, "DeleteExternalDirs") == 0) {
     r = ci::PerformExternalDirectoryDeletionForAllUsers(std::string(val));
+  } else if (g_strcmp0(method_name, "CreateLegacyDirs") == 0) {
+    r = ci::CreateLegacyDirectories(std::string(val));
+  } else if (g_strcmp0(method_name, "DeleteLegacyDirs") == 0) {
+    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 {
     LOG(ERROR) << "Unknown method call: " << method_name;
   }