#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(),
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
-