From 18d8aec9d868f0baac91c76b5dfb713d3e0b82a1 Mon Sep 17 00:00:00 2001 From: Tomasz Iwanek Date: Fri, 15 Jul 2016 10:41:54 +0200 Subject: [PATCH] Fix StepDeltaPatch and ExternalMount Following changes allows StepDeltaPatch step to work with package which is installed in external memory. Additional abstraction of ExternalMount is added to enable/disable package for delta update mode. Change-Id: I686ccd356f2c061d24e3a8a2b625232b57506ffc --- src/common/CMakeLists.txt | 3 ++ src/common/external_mount.cc | 58 ++++++++++++++++++++++ src/common/external_mount.h | 38 ++++++++++++++ src/common/external_storage.cc | 13 ++--- src/common/external_storage.h | 5 ++ src/common/installer_context.h | 6 +++ src/common/step/filesystem/step_delta_patch.cc | 38 +++++++++++++- .../step/filesystem/step_disable_external_mount.cc | 23 +++++++++ .../step/filesystem/step_disable_external_mount.h | 31 ++++++++++++ .../step/filesystem/step_enable_external_mount.cc | 41 +++++++++++++++ .../step/filesystem/step_enable_external_mount.h | 31 ++++++++++++ 11 files changed, 277 insertions(+), 10 deletions(-) create mode 100644 src/common/external_mount.cc create mode 100644 src/common/external_mount.h create mode 100644 src/common/step/filesystem/step_disable_external_mount.cc create mode 100644 src/common/step/filesystem/step_disable_external_mount.h create mode 100644 src/common/step/filesystem/step_enable_external_mount.cc create mode 100644 src/common/step/filesystem/step_enable_external_mount.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 98b3959..dac9a07 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -3,6 +3,7 @@ SET(SRCS privileges.cc app_installer.cc certificate_validation.cc + external_mount.cc external_storage.cc feature_validator.cc installer_context.cc @@ -44,6 +45,8 @@ SET(SRCS step/filesystem/step_create_legacy_directories.cc step/filesystem/step_create_storage_directories.cc step/filesystem/step_delta_patch.cc + step/filesystem/step_disable_external_mount.cc + step/filesystem/step_enable_external_mount.cc step/filesystem/step_move_installed_storage.cc step/filesystem/step_recover_files.cc step/filesystem/step_recover_icons.cc diff --git a/src/common/external_mount.cc b/src/common/external_mount.cc new file mode 100644 index 0000000..8762629 --- /dev/null +++ b/src/common/external_mount.cc @@ -0,0 +1,58 @@ +// 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/external_mount.h" + +#include +#include + +namespace common_installer { + +ExternalMount::ExternalMount(const std::string& pkgid, uid_t uid) + : pkgid_(pkgid), + uid_(uid), + mounted_(false) { +} + +ExternalMount::~ExternalMount() { + if (mounted_) { + int ret = app2ext_usr_disable_external_pkg(pkgid_.c_str(), uid_); + if (ret < 0) { + LOG(ERROR) << "app2ext_usr_disable_external_pkg failed with error code: " + << ret; + } + } +} + +bool ExternalMount::IsAvailable() const { + return app2ext_usr_get_app_location(pkgid_.c_str(), uid_) == APP2EXT_SD_CARD; +} + +bool ExternalMount::Mount() { + if (mounted_) + return true; + int ret = app2ext_usr_enable_external_pkg(pkgid_.c_str(), uid_); + if (ret < 0) { + LOG(ERROR) << "app2ext_usr_enable_external_pkg failed with error code: " + << ret; + return false; + } + mounted_ = true; + return true; +} + +bool ExternalMount::Umount() { + if (!mounted_) + return true; + int ret = app2ext_usr_disable_external_pkg(pkgid_.c_str(), uid_); + if (ret < 0) { + LOG(ERROR) << "app2ext_usr_disable_external_pkg failed with error code: " + << ret; + return false; + } + mounted_ = false; + return true; +} + +} // namespace common_installer diff --git a/src/common/external_mount.h b/src/common/external_mount.h new file mode 100644 index 0000000..d37ddc9 --- /dev/null +++ b/src/common/external_mount.h @@ -0,0 +1,38 @@ +// 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_EXTERNAL_MOUNT_H_ +#define COMMON_EXTERNAL_MOUNT_H_ + +#include + +#include + +namespace common_installer { + +/** + * @brief The ExternalMount class + * Class used to mount package content for runtime. + * + * This class is used by delta update mode to get old content of package to + * create the new content of package. + */ +class ExternalMount { + public: + ExternalMount(const std::string& pkgid, uid_t uid); + ~ExternalMount(); + + bool IsAvailable() const; + bool Mount(); + bool Umount(); + + private: + std::string pkgid_; + uid_t uid_; + bool mounted_; +}; + +} // namespace common_installer + +#endif // COMMON_EXTERNAL_MOUNT_H_ diff --git a/src/common/external_storage.cc b/src/common/external_storage.cc index a35bdc3..2ea3584 100644 --- a/src/common/external_storage.cc +++ b/src/common/external_storage.cc @@ -78,26 +78,23 @@ ExternalStorage::~ExternalStorage() { bool ExternalStorage::Finalize(bool success) { int ret = APP2EXT_STATUS_SUCCESS; switch (type_) { - case RequestType::Install: { + case RequestType::Install: ret = handle_->interface.client_usr_post_install(pkgid_.c_str(), success ? APP2EXT_STATUS_SUCCESS : APP2EXT_STATUS_FAILED, uid_); break; - } - case RequestType::Update: { + case RequestType::Update: + case RequestType::Delta: ret = handle_->interface.client_usr_post_upgrade(pkgid_.c_str(), success ? APP2EXT_STATUS_SUCCESS : APP2EXT_STATUS_FAILED, uid_); break; - } - case RequestType::Uninstall: { + case RequestType::Uninstall: ret = handle_->interface.client_usr_post_uninstall(pkgid_.c_str(), uid_); break; - } - case RequestType::Move: { + case RequestType::Move: ret = handle_->interface.client_usr_post_move(pkgid_.c_str(), static_cast(move_type_), uid_); break; - } default: assert(false && "Not supported installation mode"); } diff --git a/src/common/external_storage.h b/src/common/external_storage.h index 05d7f4f..ae8f7cb 100644 --- a/src/common/external_storage.h +++ b/src/common/external_storage.h @@ -17,6 +17,11 @@ namespace common_installer { +/** + * @brief The ExternalStorage class + * Encapsulates mounting package in external memory for performing + * installation request. + */ class ExternalStorage final { public: static std::unique_ptr MoveInstalledStorage( diff --git a/src/common/installer_context.h b/src/common/installer_context.h index 2cafbec..e448c67 100644 --- a/src/common/installer_context.h +++ b/src/common/installer_context.h @@ -19,6 +19,7 @@ #include #include +#include "common/external_mount.h" #include "common/external_storage.h" #include "common/pkgmgr_interface.h" #include "common/recovery_file.h" @@ -325,6 +326,11 @@ class InstallerContext { * @brief External Storage object if installing in external */ std::unique_ptr external_storage; + + /** + * @brief External package mount object if delta update with external + */ + std::unique_ptr external_mount; }; } // namespace common_installer diff --git a/src/common/step/filesystem/step_delta_patch.cc b/src/common/step/filesystem/step_delta_patch.cc index d454354..bd28b7f 100644 --- a/src/common/step/filesystem/step_delta_patch.cc +++ b/src/common/step/filesystem/step_delta_patch.cc @@ -12,6 +12,7 @@ #include #include +#include #include #include "common/utils/file_util.h" @@ -32,6 +33,8 @@ const char kSharedTrusted[] = "shared/trusted"; const char kDeltaFile[] = "delta_info.xml"; const char kXDeltaBinary[] = "/usr/bin/xdelta3"; +const char kExternalMemoryMountPoint[] = ".mmc"; + bool ValidateDeltaInfo(const delta::DeltaInfo& info) { for (auto& item : info.added()) { if (ci::HasDirectoryClimbing(item)) @@ -190,6 +193,35 @@ bool ApplyPatch(const delta::DeltaInfo& info, const bf::path& app_dir, return true; } +bool CopySkipMount(const bf::path& from, const bf::path& to) { + bs::error_code error; + bf::create_directory(to, error); + if (error) { + LOG(ERROR) << "Failed to create target directory"; + return false; + } + for (bf::directory_iterator iter(from); iter != bf::directory_iterator(); + ++iter) { + if (iter->path().filename() == kExternalMemoryMountPoint) + continue; + + if (bf::is_directory(iter->path())) { + if (!ci::CopyDir(iter->path(), to / iter->path().filename())) { + LOG(ERROR) << "Failed to create copy of: " << iter->path(); + return false; + } + } else { + bs::error_code error; + bf::copy(iter->path(), to / iter->path().filename(), error); + if (error) { + LOG(ERROR) << "Failed to create copy of: " << iter->path(); + return false; + } + } + } + return true; +} + } // namespace namespace common_installer { @@ -246,8 +278,10 @@ Step::Status StepDeltaPatch::process() { return Status::DELTA_ERROR; } - if (!CopyDir(context_->root_application_path.get() / context_->pkgid.get() - / delta_root_, context_->unpacked_dir_path.get())) { + if (!CopySkipMount( + context_->root_application_path.get() / context_->pkgid.get() + / delta_root_, + context_->unpacked_dir_path.get())) { LOG(ERROR) << "Failed to copy package files"; return Status::DELTA_ERROR; } diff --git a/src/common/step/filesystem/step_disable_external_mount.cc b/src/common/step/filesystem/step_disable_external_mount.cc new file mode 100644 index 0000000..f135f00 --- /dev/null +++ b/src/common/step/filesystem/step_disable_external_mount.cc @@ -0,0 +1,23 @@ +// 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_disable_external_mount.h" + +namespace common_installer { +namespace filesystem { + +Step::Status StepDisableExternalMount::process() { + if (context_->external_mount) { + if (!context_->external_mount->Umount()) { + LOG(ERROR) << "Failed to unmount package for request"; + return Status::APP_DIR_ERROR; + } + } + context_->external_mount.reset(); + LOG(DEBUG) << "External mount removed"; + return Status::OK; +} + +} // namespace filesystem +} // namespace common_installer diff --git a/src/common/step/filesystem/step_disable_external_mount.h b/src/common/step/filesystem/step_disable_external_mount.h new file mode 100644 index 0000000..74d7bbc --- /dev/null +++ b/src/common/step/filesystem/step_disable_external_mount.h @@ -0,0 +1,31 @@ +// 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_DISABLE_EXTERNAL_MOUNT_H_ +#define COMMON_STEP_FILESYSTEM_STEP_DISABLE_EXTERNAL_MOUNT_H_ + +#include + +#include "common/installer_context.h" +#include "common/step/step.h" + +namespace common_installer { +namespace filesystem { + +class StepDisableExternalMount : public 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(StepDisableExternalMount) +}; + +} // namespace filesystem +} // namespace common_installer + +#endif // COMMON_STEP_FILESYSTEM_STEP_DISABLE_EXTERNAL_MOUNT_H_ diff --git a/src/common/step/filesystem/step_enable_external_mount.cc b/src/common/step/filesystem/step_enable_external_mount.cc new file mode 100644 index 0000000..13c2489 --- /dev/null +++ b/src/common/step/filesystem/step_enable_external_mount.cc @@ -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. + +#include "common/step/filesystem/step_enable_external_mount.h" + +#include "common/external_mount.h" + +namespace common_installer { +namespace filesystem { + +Step::Status StepEnableExternalMount::process() { + std::unique_ptr mount(new ExternalMount(context_->pkgid.get(), + context_->uid.get())); + if (!mount->IsAvailable()) { + LOG(DEBUG) << "External mount not available for package"; + return Status::OK; + } + + if (!mount->Mount()) { + LOG(ERROR) << "Failed to mount package for request"; + return Status::APP_DIR_ERROR; + } + context_->external_mount = std::move(mount); + LOG(DEBUG) << "External mount created"; + return Status::OK; +} + +Step::Status StepEnableExternalMount::undo() { + if (context_->external_mount) { + if (!context_->external_mount->Umount()) { + LOG(ERROR) << "Failed to unmount package"; + return Status::APP_DIR_ERROR; + } + } + return Status::OK; +} + +} // namespace filesystem +} // namespace common_installer + diff --git a/src/common/step/filesystem/step_enable_external_mount.h b/src/common/step/filesystem/step_enable_external_mount.h new file mode 100644 index 0000000..3b30c18 --- /dev/null +++ b/src/common/step/filesystem/step_enable_external_mount.h @@ -0,0 +1,31 @@ +// 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_ENABLE_EXTERNAL_MOUNT_H_ +#define COMMON_STEP_FILESYSTEM_STEP_ENABLE_EXTERNAL_MOUNT_H_ + +#include + +#include "common/installer_context.h" +#include "common/step/step.h" + +namespace common_installer { +namespace filesystem { + +class StepEnableExternalMount : public Step { + public: + using Step::Step; + + Status process() override; + Status clean() override { return Status::OK; } + Status undo() override; + Status precheck() override { return Status::OK; } + + STEP_NAME(StepEnableExternalMount) +}; + +} // namespace filesystem +} // namespace common_installer + +#endif // COMMON_STEP_FILESYSTEM_STEP_ENABLE_EXTERNAL_MOUNT_H_ -- 2.7.4