Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / step / filesystem / step_move_installed_storage.cc
index 2ca8f18..257b5d9 100644 (file)
 
 #include "common/step/filesystem/step_move_installed_storage.h"
 
+#include <tzplatform_config.h>
+
+#include <cstring>
+#include <filesystem>
+#include <string>
+#include <system_error>
+
 #include "common/external_storage.h"
+#include "common/shared_dirs.h"
+#include "common/utils/file_util.h"
+#include "common/utils/paths.h"
+#include "common/pkgmgr_registration.h"
+#include "common/utils/pkgmgr_query.h"
+
+namespace fs = std::filesystem;
+
+namespace {
+
+const char kInternalOnly[] = "internal-only";
+
+bool MoveFileAndUpdateTepInfo(const std::filesystem::path& src,
+    const std::filesystem::path& dst,
+    const common_installer::InstallerContext* context) {
+  if (!fs::exists(src))
+    return true;
+
+  if (!common_installer::MoveFile(src, dst)) {
+    LOG(ERROR) << "Cannot move tep file from: " << src
+               << " to " << dst;
+    return false;
+  }
+
+  if (!common_installer::UpdateTepInfoInPkgmgr(dst, context->pkgid.get(),
+      context->uid.get(), context->request_mode.get())) {
+    LOG(ERROR) << "Failed to update tep package location in pkgmgr";
+    return false;
+  }
+  return true;
+}
+
+}  // namespace
 
 namespace common_installer {
 namespace filesystem {
 
+StepMoveInstalledStorage::StepMoveInstalledStorage(InstallerContext* context)
+    : Step(context), move_type_(MoveType::NONE) {
+}
+
 Step::Status StepMoveInstalledStorage::process() {
+  PkgQueryInterface pkg_query(context_->pkgid.get(),
+      context_->uid.get());
+  std::string installed_storage = pkg_query.StorageForPkgId();
+
+  if ((move_type_ == MoveType::TO_INTERNAL &&
+          installed_storage == "installed_external") ||
+      (move_type_ == MoveType::TO_EXTERNAL &&
+          installed_storage == "installed_internal")) {
+    if (!MoveExternal())
+      return Status::APP_DIR_ERROR;
+  } else if (
+      (move_type_ == MoveType::TO_INTERNAL &&
+          installed_storage == "installed_extended") ||
+      (move_type_ == MoveType::TO_EXTENDED &&
+          installed_storage == "installed_internal")) {
+    if (!MoveExtended())
+      return Status::APP_DIR_ERROR;
+  }
+  return Status::OK;
+}
+
+Step::Status StepMoveInstalledStorage::undo() {
+  if (context_->external_storage) {
+    if (new_tep_location_ != old_tep_location_)
+      if (!MoveBackTep())
+        return Status::APP_DIR_ERROR;
+    MoveBackExternal();
+  } else {
+    if (!MoveBackExtended())
+      return Status::APP_DIR_ERROR;
+  }
+  return Status::OK;
+}
+
+Step::Status StepMoveInstalledStorage::clean() {
+  if (context_->external_storage)
+    context_->external_storage->Commit();
+  return Status::OK;
+}
+
+Step::Status StepMoveInstalledStorage::precheck() {
+  move_type_ = context_->move_type.get();
+  if (context_->manifest_data.get()->installlocation == nullptr) {
+    LOG(ERROR) << "Cannot get installlocation value";
+    return Status::INVALID_VALUE;
+  }
+  if (!strcmp(context_->manifest_data.get()->installlocation, kInternalOnly)) {
+    LOG(ERROR) << "This package is interanl-only";
+    return Status::OPERATION_NOT_ALLOWED;
+  }
+  return Status::OK;
+}
+
+void StepMoveInstalledStorage::SetTepPaths() {
+  old_tep_location_ = context_->manifest_data.get()->tep_name;
+  if (context_->is_move_to_external.get()) {
+    new_tep_location_ = GetExternalTepPath(context_->request_mode.get(),
+                                       context_->uid.get());
+    new_tep_location_ /= old_tep_location_.filename();
+  } else {
+    new_tep_location_ = GetInternalTepPath(context_->GetPkgPath()) /
+        old_tep_location_.filename();
+  }
+}
+
+bool StepMoveInstalledStorage::MoveTep() {
+  if (!fs::exists(new_tep_location_.parent_path())) {
+    std::error_code error;
+    fs::create_directory(new_tep_location_.parent_path(), error);
+    if (error) {
+      LOG(ERROR) << "Failed to destination path for new tep location";
+      return false;
+    }
+  }
+
+  return MoveFileAndUpdateTepInfo(old_tep_location_, new_tep_location_,
+      context_);
+}
+
+bool StepMoveInstalledStorage::MoveBackTep() {
+  return MoveFileAndUpdateTepInfo(new_tep_location_, old_tep_location_,
+      context_);
+}
+
+bool StepMoveInstalledStorage::MoveExternal() {
   context_->external_storage =
       ExternalStorage::MoveInstalledStorage(context_->request_type.get(),
           context_->root_application_path.get(),
@@ -19,12 +148,101 @@ Step::Status StepMoveInstalledStorage::process() {
           context_->is_move_to_external.get());
   if (!context_->external_storage) {
     LOG(ERROR) << "Cannot initialize external storage for move";
-    return Status::APP_DIR_ERROR;
+    return false;
   }
 
-  return Status::OK;
+  // move tep
+  if (context_->manifest_data.get()->tep_name) {
+    SetTepPaths();
+
+    if (new_tep_location_ != old_tep_location_)
+      if (!MoveTep())
+        return false;
+  }
+  return true;
+}
+
+bool StepMoveInstalledStorage::MoveBackExternal() {
+  context_->external_storage->Abort();
+  return true;
+}
+
+bool StepMoveInstalledStorage::MoveExtended() {
+  if (move_type_ == MoveType::TO_EXTENDED) {
+    old_pkg_location_ = context_->GetPkgPath();
+    new_pkg_location_ = fs::path(GetExtendedRootAppPath(context_->uid.get())) /
+        context_->pkgid.get();
+    context_->storage.set(Storage::EXTENDED);
+  } else {
+    old_pkg_location_ = fs::path(GetExtendedRootAppPath(context_->uid.get())) /
+        context_->pkgid.get();
+    new_pkg_location_ = fs::path(GetRootAppPath(
+        context_->is_readonly_package.get(), context_->uid.get())) /
+        context_->pkgid.get();
+    context_->storage.set(Storage::INTERNAL);
+  }
+
+  if (move_type_ == MoveType::TO_INTERNAL) {
+    // remove existing symlink
+    if (!Remove(new_pkg_location_))
+      return false;
+  }
+
+  if (!MoveDir(old_pkg_location_, new_pkg_location_))
+    return false;
+
+  // create symlink for extended path
+  if (move_type_ == MoveType::TO_EXTENDED) {
+    std::error_code error;
+    fs::create_symlink(new_pkg_location_, old_pkg_location_, error);
+    if (error) {
+      LOG(ERROR) << "Failed to create symlink for extended path: "
+                 << error.message();
+    }
+  }
+
+  if (!SetPackageDirectoryOwnerAndPermissions(new_pkg_location_,
+      context_->uid.get())) {
+    LOG(ERROR) << "Failed to set directory ownership";
+    return false;
+  }
+
+  if (!UpdateInstalledStorageInPkgmgr(context_->storage.get(),
+      new_pkg_location_, context_->pkgid.get(), context_->uid.get()))
+    return false;
+  return true;
+}
+
+bool StepMoveInstalledStorage::MoveBackExtended() {
+  if (move_type_ == MoveType::TO_EXTENDED) {
+    // Remove symlink if exist
+    if (fs::exists(old_pkg_location_) &&
+        fs::is_symlink(symlink_status(old_pkg_location_))) {
+      if (!Remove(old_pkg_location_)) {
+        LOG(ERROR) << "Failed to remove symlink for extended path";
+        return false;
+      }
+    }
+  }
+  MoveDir(new_pkg_location_, old_pkg_location_);
+  if (move_type_ == MoveType::TO_INTERNAL) {
+    std::error_code error;
+    fs::create_symlink(old_pkg_location_, new_pkg_location_, error);
+    if (error) {
+      LOG(ERROR) << "Failed to create symlink for extended path: "
+                 << error.message();
+      return false;
+    }
+  }
+
+  if (!SetPackageDirectoryOwnerAndPermissions(old_pkg_location_,
+      context_->uid.get())) {
+    LOG(ERROR) << "Failed to set directory ownership";
+    return false;
+  }
+
+  return true;
 }
 
 }  // namespace filesystem
 }  // namespace common_installer
-