Move GetLightUserList() to user_util.h
[platform/core/appfw/app-installers.git] / src / common / step / filesystem / step_remove_files.cc
index 2616d19..63d3c6c 100644 (file)
 #include <string>
 #include <vector>
 
-#include "common/pkgmgr_query.h"
+#include "common/utils/pkgmgr_query.h"
+#include "common/utils/file_util.h"
+#include "common/utils/user_util.h"
+#include "common/shared_dirs.h"
 
 namespace bs = boost::system;
 namespace bf = boost::filesystem;
@@ -22,17 +25,31 @@ namespace bf = boost::filesystem;
 namespace {
 
 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+const char kSubsesionDir[] = "subsession";
 
-bool SkipDirectoryIfGlobal(const bf::path& path) {
+bool SkipRWDirectories(const bf::path& path) {
   static const std::vector<std::string> dirs_to_ignore = {
     {"cache"},
     {"data"},
-    {"shared"},
+    {"shared/data"},
+    {"shared/cache"},
+    {"shared/trusted"},
   };
   return std::find(dirs_to_ignore.begin(), dirs_to_ignore.end(), path) !=
       dirs_to_ignore.end();
 }
 
+bool RemoveSignature(const std::string& pkgid, bool is_readonly) {
+  bf::path signature_path = bf::path(is_readonly ?
+      tzplatform_getenv(TZ_SYS_RO_SHARE) : tzplatform_getenv(TZ_SYS_SHARE)) /
+          "signatures";
+  signature_path /= std::string(pkgid + ".txt");
+  if (!common_installer::Remove(signature_path))
+    return false;
+
+  return true;
+}
+
 }  // namespace
 
 
@@ -47,54 +64,90 @@ Step::Status StepRemoveFiles::precheck() {
 
   // Even though, the below checks can fail, StepRemoveFiles should still try
   // to remove the files
-  if (context_->pkg_path.get().empty())
+  if (context_->GetPkgPath().empty())
     LOG(ERROR) << "pkg_path attribute is empty";
-  else if (!bf::exists(context_->pkg_path.get()))
+  else if (!bf::exists(context_->GetPkgPath()))
     LOG(ERROR) << "pkg_path ("
-               << context_->pkg_path.get()
+               << context_->GetPkgPath()
                << ") path does not exist";
 
   return Step::Status::OK;
 }
 
 Step::Status StepRemoveFiles::process() {
-  bs::error_code error;
-  bf::path pkg_path(context_->pkg_path.get());
-
   // We need to unmount external storage before removing package directory
   // because mount point is inside
   if (context_->external_storage)
     context_->external_storage->Commit();
 
-  if (QueryIsPackageInstalled(context_->pkgid.get(), kGlobalUserUid)) {
-    for (bf::directory_iterator itr(pkg_path); itr != bf::directory_iterator();
-        ++itr) {
-      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;
-        }
-        bf::remove_all(itr->path(), error);
-        if (error) {
-          LOG(ERROR) << "Can't remove dir:" << context_->pkg_path.get().c_str();
+  bool is_keep_rwdata = false;
+  if (context_->request_mode.get() != RequestMode::GLOBAL) {
+    PkgQueryInterface pkg_query(context_->pkgid.get(), kGlobalUserUid);
+    if (pkg_query.IsPackageInstalled() ||
+        context_->keep_rwdata.get())
+      is_keep_rwdata = true;
+  }
+
+  bool is_error = false;
+  std::vector<bf::path> root_paths;
+  // Use RootAppPath + Pkgid because of ReadonlyUpdateUninstall
+  root_paths.push_back(context_->root_application_path.get());
+
+  for (auto& lw_user : GetLightUserList(context_->uid.get()))
+    root_paths.push_back(context_->root_application_path.get() / kSubsesionDir /
+                        lw_user);
+
+  for (auto& root_path : root_paths) {
+    if (is_keep_rwdata) {
+      bool ret;
+      for (bf::directory_iterator itr(root_path / context_->pkgid.get());
+          itr != bf::directory_iterator(); ++itr) {
+        if (bf::is_directory(itr->status())) {
+          if (SkipRWDirectories(itr->path().leaf())) {
+            LOG(DEBUG) << "Skipping remove dir:" << itr->path().c_str();
+            continue;
+          }
+          ret = RemoveAll(itr->path());
+        } else {
+          ret = Remove(itr->path());
         }
-      } else if (bf::is_regular_file(itr->status())) {
-        bf::remove_all(itr->path(), error);
+        if (!ret)
+          is_error = true;
       }
-    }
-  } else {
-    bf::remove_all(pkg_path, error);
-    if (error) {
-      LOG(ERROR) << "Can't remove directory:" <<
-          context_->pkg_path.get().c_str();
     } else {
-      LOG(DEBUG) << "Removed directory: " << context_->pkg_path.get();
+      if (!RemoveAll(root_path / context_->pkgid.get()) ||
+          !common_installer::DeleteSharedDirectories(root_path,
+              context_->pkgid.get()))
+        is_error = true;
+    }
+
+    if (is_error)
+      return Status::ERROR;
+  }
+
+  // Remove package files at extended storage
+  if (context_->storage.get() == Storage::EXTENDED) {
+    bf::path extended_path =
+        bf::path(GetExtendedRootAppPath(context_->uid.get())) /
+            context_->pkgid.get();
+    if (!RemoveAll(extended_path))
+      return Status::APP_DIR_ERROR;
+  }
+
+  for (auto& lw_user : GetLightUserList(context_->uid.get())) {
+    if (context_->storage.get() == Storage::EXTENDED) {
+      bf::path extended_path =
+          bf::path(GetExtendedRootAppPath(context_->uid.get())) /
+          kSubsesionDir / lw_user / context_->pkgid.get();
+      if (!RemoveAll(extended_path))
+        return Status::APP_DIR_ERROR;
     }
   }
 
+  // Remove stored signature file
+  if (!RemoveSignature(context_->pkgid.get(),
+                        context_->is_readonly_package.get()))
+    return Status::APP_DIR_ERROR;
 
   return Status::OK;
 }