Mount install is run by "-w $pkgid" option.
Mount install, update mount install and deinstallation of mount-installed
package should work.
Requires:
- https://review.tizen.org/gerrit/#/c/65361/
Change-Id: Ic2f2b3b0cbb96493e37bd871757a2f7ffc0638a1
step/filesystem/step_check_pkg_directory_path.cc
step/filesystem/step_create_symbolic_link.cc
step/filesystem/step_tpk_patch_icons.cc
+ step/filesystem/step_tpk_prepare_package_directory.cc
+ step/filesystem/step_tpk_update_package_directory.cc
step/pkgmgr/step_convert_xml.cc
step/pkgmgr/step_manifest_adjustment.cc
step/rds/step_tpk_rds_modify.cc
--- /dev/null
+// 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 "tpk/step/filesystem/step_tpk_prepare_package_directory.h"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <common/backup_paths.h>
+#include <common/utils/file_util.h>
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+namespace ci = common_installer;
+
+namespace {
+
+const std::vector<std::string> kExtractEntries = {
+ "bin",
+ "lib",
+ "shared/res"
+};
+
+const std::vector<std::string> kSymlinkEntries = {
+ "res",
+ "tizen-manifest.xml",
+ "author-signature.xml",
+ "signature1.xml",
+ "signature2.xml"
+};
+
+bool ReplacePaths(const bf::path& source, const bf::path& destination) {
+ if (!bf::exists(destination.parent_path())) {
+ bs::error_code error;
+ bf::create_directories(destination.parent_path(), error);
+ if (error) {
+ LOG(ERROR) << "Failed to create destination directory for directory "
+ << "backup";
+ return false;
+ }
+ }
+ if (!ci::MoveDir(source, destination)) {
+ LOG(ERROR) << "Failed to move " << source << " to " << destination;
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+namespace tpk {
+namespace filesystem {
+
+ci::Step::Status StepTpkPreparePackageDirectory::PrepareDirectory(
+ const std::string& entry) {
+ // Due to the fact that boost fails to return correct parent_path() then path
+ // with ending '/' is passed, kExtractEntries has not ending slash
+ // here, we need to filter only directories and ci::ExtractToTmpDir() has
+ // simple string filter so we append slash character here
+ std::string filter = entry + '/';
+ if (!ci::ExtractToTmpDir(context_->file_path.get().c_str(),
+ context_->pkg_path.get(), entry)) {
+ LOG(ERROR) << "Failed to extract from zip files in: " << filter;
+ return Status::UNZIP_ERROR;
+ }
+ return Status::OK;
+}
+
+ci::Step::Status StepTpkPreparePackageDirectory::PrepareLink(
+ const std::string& entry, const bf::path& mount_point) {
+ bs::error_code error;
+ bf::path mount_point_entry = mount_point / entry;
+ if (bf::exists(mount_point_entry)) {
+ bf::path destination = context_->pkg_path.get() / entry;
+ if (bf::exists(destination)) {
+ if (!bf::is_symlink(destination)) {
+ LOG(ERROR) << "Cannot proceed. "
+ << "Location of link is used by another file";
+ return Status::APP_DIR_ERROR;
+ }
+ bf::remove(destination, error);
+ if (error) {
+ LOG(ERROR) << "Failed to remove previous symlink";
+ return Status::APP_DIR_ERROR;
+ }
+ }
+ bf::create_symlink(mount_point_entry, destination, error);
+ if (error) {
+ LOG(ERROR) << "Failed to create symlink for entry: " << mount_point_entry;
+ return Status::APP_DIR_ERROR;
+ }
+ }
+ return Status::OK;
+}
+
+
+ci::Step::Status StepTpkPreparePackageDirectory::ExtractEntries() {
+ LOG(DEBUG) << "Extracting entries from zip package...";
+ for (auto& entry : GetExtractEntries()) {
+ LOG(DEBUG) << "Extracting: " << entry;
+ auto status = PrepareDirectory(entry);
+ if (status != Status::OK)
+ return status;
+ }
+ return Status::OK;
+}
+
+ci::Step::Status StepTpkPreparePackageDirectory::PrepareLinks() {
+ bf::path mount_point = ci::GetMountLocation(context_->pkg_path.get());
+ LOG(DEBUG) << "Creating symlinks to zip package...";
+ for (auto& link_entry : kSymlinkEntries) {
+ LOG(DEBUG) << "Symlink: " << link_entry;
+ auto status = PrepareLink(link_entry, mount_point);
+ if (status != Status::OK)
+ return status;
+ }
+ return Status::OK;
+}
+
+ci::Step::Status StepTpkPreparePackageDirectory::process() {
+ auto status = ExtractEntries();
+ if (status != Status::OK)
+ return status;
+ return PrepareLinks();
+}
+
+ci::Step::Status StepTpkPreparePackageDirectory::precheck() {
+ if (context_->pkg_path.get().empty()) {
+ LOG(ERROR) << "Package installation path is not set";
+ return Status::INVALID_VALUE;
+ }
+ return Status::OK;
+}
+
+const std::vector<std::string>&
+StepTpkPreparePackageDirectory::GetExtractEntries() const {
+ return kExtractEntries;
+}
+
+} // namespace filesystem
+} // namespace tpk
--- /dev/null
+// 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 TPK_STEP_FILESYSTEM_STEP_TPK_PREPARE_PACKAGE_DIRECTORY_H_
+#define TPK_STEP_FILESYSTEM_STEP_TPK_PREPARE_PACKAGE_DIRECTORY_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <boost/filesystem/path.hpp>
+
+#include <common/installer_context.h>
+#include <common/step/step.h>
+
+#include <pkgmgrinfo_basic.h>
+
+#include <string>
+#include <vector>
+
+namespace tpk {
+namespace filesystem {
+
+/**
+ * \brief Responsible for adjusting package directory after mounting zip package
+ * by StepMountInstall
+ *
+ * This step will:
+ *
+ * 1) Extract partially content of zip package binaries must be extracted from:
+ * - bin/
+ * - lib/
+ * - shared/res/
+ *
+ * 2) Create symlinks for following files and directories to point them to
+ * mount path:
+ * - tizen-manifest.xml
+ * - author-signature.xml
+ * - signature*.xml
+ * - res/
+ */
+class StepTpkPreparePackageDirectory : 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;
+
+ protected:
+ Status PrepareDirectory(const std::string& entry);
+ Status PrepareLinks();
+ Status ExtractEntries();
+ Status PrepareLink(const std::string& entry,
+ const boost::filesystem::path& mount_point);
+ const std::vector<std::string>& GetExtractEntries() const;
+
+ SCOPE_LOG_TAG(TpkPreparePackageDirectory)
+};
+
+} // namespace filesystem
+} // namespace tpk
+
+#endif // TPK_STEP_FILESYSTEM_STEP_TPK_PREPARE_PACKAGE_DIRECTORY_H_
--- /dev/null
+// 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 "tpk/step/filesystem/step_tpk_update_package_directory.h"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <common/backup_paths.h>
+#include <common/utils/file_util.h>
+
+#include <vector>
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+namespace ci = common_installer;
+
+namespace {
+
+bool ReplacePaths(const bf::path& source, const bf::path& destination) {
+ if (!bf::exists(destination.parent_path())) {
+ bs::error_code error;
+ bf::create_directories(destination.parent_path(), error);
+ if (error) {
+ LOG(ERROR) << "Failed to create destination directory for directory "
+ << "backup";
+ return false;
+ }
+ }
+ if (!ci::MoveDir(source, destination)) {
+ LOG(ERROR) << "Failed to move " << source << " to " << destination;
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+namespace tpk {
+namespace filesystem {
+
+ci::Step::Status StepTpkUpdatePackageDirectory::BackupDirectory(
+ const std::string& entry, const boost::filesystem::path& backup_path) {
+ bf::path source = context_->pkg_path.get() / entry;
+ if (bf::exists(source)) {
+ bf::path destination = backup_path / entry;
+ if (!ReplacePaths(source, destination))
+ return Status::APP_DIR_ERROR;
+ }
+ return Status::OK;
+}
+
+ci::Step::Status StepTpkUpdatePackageDirectory::RestoreDirectory(
+ const std::string& entry, const boost::filesystem::path& backup_path) {
+ // restore backup if directory exists
+ if (bf::exists(backup_path / entry)) {
+ bf::path source = backup_path / entry;
+ bf::path destination = context_->pkg_path.get() / entry;
+ if (!ReplacePaths(source, destination))
+ return Status::APP_DIR_ERROR;
+ }
+ return Status::OK;
+}
+
+ci::Step::Status StepTpkUpdatePackageDirectory::BackupEntries() {
+ bf::path backup_path =
+ ci::GetBackupPathForPackagePath(context_->pkg_path.get());
+ for (auto& entry : GetExtractEntries()) {
+ auto status = BackupDirectory(entry, backup_path);
+ if (status != Status::OK)
+ return status;
+ }
+ return Status::OK;
+}
+
+ci::Step::Status StepTpkUpdatePackageDirectory::process() {
+ auto status = BackupEntries();
+ if (status != Status::OK)
+ return status;
+ status = ExtractEntries();
+ if (status != Status::OK)
+ return status;
+ return PrepareLinks();
+}
+
+ci::Step::Status StepTpkUpdatePackageDirectory::clean() {
+ bf::path backup_path =
+ ci::GetBackupPathForPackagePath(context_->pkg_path.get());
+ if (bf::exists(backup_path)) {
+ bs::error_code error;
+ bf::remove(backup_path, error);
+ if (error) {
+ LOG(ERROR) << "Failed to remove backup path: " << backup_path;
+ return Status::APP_DIR_ERROR;
+ }
+ }
+ return Status::OK;
+}
+
+ci::Step::Status StepTpkUpdatePackageDirectory::undo() {
+ bf::path backup_path =
+ ci::GetBackupPathForPackagePath(context_->pkg_path.get());
+
+ for (auto& entry : GetExtractEntries()) {
+ auto status = RestoreDirectory(entry, backup_path);
+ if (status != Status::OK)
+ return status;
+ }
+ return Status::OK;
+}
+
+} // namespace filesystem
+} // namespace tpk
--- /dev/null
+// 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 TPK_STEP_FILESYSTEM_STEP_TPK_UPDATE_PACKAGE_DIRECTORY_H_
+#define TPK_STEP_FILESYSTEM_STEP_TPK_UPDATE_PACKAGE_DIRECTORY_H_
+
+#include <boost/filesystem/path.hpp>
+#include <manifest_parser/utils/logging.h>
+
+#include <string>
+
+#include "tpk/step/filesystem/step_tpk_prepare_package_directory.h"
+
+namespace tpk {
+namespace filesystem {
+
+/**
+ * \brief Responsible for adjusting package directory after mounting zip package
+ * by StepMountUpdate
+ *
+ * This step will, additionally to base step actions, ,aintain backup
+ * of directories from point 1) for operation rollback scenario.
+ */
+class StepTpkUpdatePackageDirectory : public StepTpkPreparePackageDirectory {
+ public:
+ using StepTpkPreparePackageDirectory::StepTpkPreparePackageDirectory;
+
+ Status process() override;
+ Status clean() override;
+ Status undo() override;
+
+ private:
+ Status BackupEntries();
+ Status BackupDirectory(const std::string& entry,
+ const boost::filesystem::path& backup_path);
+ Status RestoreDirectory(const std::string& entry,
+ const boost::filesystem::path& backup_path);
+
+ SCOPE_LOG_TAG(TpkUpdatePackageDirectory)
+};
+
+} // namespace filesystem
+} // namespace tpk
+
+#endif // TPK_STEP_FILESYSTEM_STEP_TPK_UPDATE_PACKAGE_DIRECTORY_H_
std::string GetInstallationPackagePath(int argc, char** argv) {
std::string path;
for (int i = 0; i < argc; ++i) {
- if (!strcmp(argv[i], "-i")) {
+ if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "-w")) {
if (i + 1 < argc) {
path = argv[i + 1];
break;
#include <common/step/backup/step_backup_icons.h>
#include <common/step/backup/step_backup_manifest.h>
#include <common/step/backup/step_copy_backup.h>
+#include <common/step/configuration/step_block_cross_update.h>
#include <common/step/configuration/step_configure.h>
#include <common/step/configuration/step_fail.h>
#include <common/step/configuration/step_parse_manifest.h>
#include <common/step/filesystem/step_remove_icons.h>
#include <common/step/filesystem/step_remove_per_user_storage_directories.h>
#include <common/step/filesystem/step_remove_temporary_directory.h>
+#include <common/step/filesystem/step_remove_zip_image.h>
#include <common/step/filesystem/step_unzip.h>
+#include <common/step/mount/step_mount_unpacked.h>
+#include <common/step/mount/step_mount_install.h>
+#include <common/step/mount/step_mount_update.h>
#include <common/step/pkgmgr/step_check_blacklist.h>
#include <common/step/pkgmgr/step_check_removable.h>
#include <common/step/pkgmgr/step_kill_apps.h>
#include "tpk/step/configuration/step_parse_preload.h"
#include "tpk/step/filesystem/step_create_symbolic_link.h"
-#include "tpk/step/filesystem/step_tpk_patch_icons.h"
#include "tpk/step/filesystem/step_check_pkg_directory_path.h"
+#include "tpk/step/filesystem/step_tpk_patch_icons.h"
+#include "tpk/step/filesystem/step_tpk_prepare_package_directory.h"
+#include "tpk/step/filesystem/step_tpk_update_package_directory.h"
#include "tpk/step/pkgmgr/step_convert_xml.h"
#include "tpk/step/pkgmgr/step_manifest_adjustment.h"
#include "tpk/step/rds/step_tpk_rds_modify.h"
case ci::RequestType::Recovery:
RecoverySteps();
break;
+ case ci::RequestType::MountInstall:
+ MountInstallSteps();
+ break;
+ case ci::RequestType::MountUpdate:
+ MountUpdateSteps();
+ break;
case ci::RequestType::ManifestDirectInstall:
ManifestDirectInstallSteps();
break;
AddStep<ci::configuration::StepParseManifest>(
ci::configuration::StepParseManifest::ManifestLocation::INSTALLED,
ci::configuration::StepParseManifest::StoreLocation::BACKUP);
+ AddStep<ci::configuration::StepBlockCrossUpdate>();
AddStep<ci::pkgmgr::StepKillApps>();
AddStep<ci::backup::StepBackupManifest>();
AddStep<ci::backup::StepBackupIcons>();
AddStep<ci::pkgmgr::StepUnregisterApplication>();
AddStep<ci::security::StepRollbackDeinstallationSecurity>();
AddStep<ci::filesystem::StepRemoveFiles>();
+ AddStep<ci::filesystem::StepRemoveZipImage>();
AddStep<ci::filesystem::StepRemoveIcons>();
AddStep<ci::security::StepRevokeSecurity>();
AddStep<ci::pkgmgr::StepRemoveManifest>();
AddStep<ci::configuration::StepParseManifest>(
ci::configuration::StepParseManifest::ManifestLocation::INSTALLED,
ci::configuration::StepParseManifest::StoreLocation::BACKUP);
+ AddStep<ci::configuration::StepBlockCrossUpdate>();
AddStep<ci::pkgmgr::StepKillApps>();
AddStep<ci::backup::StepBackupManifest>();
AddStep<ci::backup::StepBackupIcons>();
AddStep<ci::configuration::StepParseManifest>(
ci::configuration::StepParseManifest::ManifestLocation::INSTALLED,
ci::configuration::StepParseManifest::StoreLocation::BACKUP);
+ AddStep<ci::configuration::StepBlockCrossUpdate>();
AddStep<ci::pkgmgr::StepKillApps>();
AddStep<ci::backup::StepBackupManifest>();
AddStep<ci::backup::StepBackupIcons>();
AddStep<ci::security::StepRecoverSecurity>();
}
+void TpkInstaller::MountInstallSteps() {
+ AddStep<ci::configuration::StepConfigure>(pkgmgr_);
+ AddStep<ci::mount::StepMountUnpacked>();
+ AddStep<ci::configuration::StepParseManifest>(
+ ci::configuration::StepParseManifest::ManifestLocation::PACKAGE,
+ ci::configuration::StepParseManifest::StoreLocation::NORMAL);
+ AddStep<tpk::configuration::StepParsePreload>();
+ AddStep<ci::pkgmgr::StepCheckBlacklist>();
+ AddStep<ci::security::StepCheckSignature>();
+ AddStep<ci::security::StepPrivilegeCompatibility>();
+ AddStep<tpk::security::StepCheckTpkBackgroundCategory>();
+ AddStep<ci::security::StepRollbackInstallationSecurity>();
+ AddStep<ci::mount::StepMountInstall>();
+ AddStep<tpk::filesystem::StepTpkPreparePackageDirectory>();
+ AddStep<ci::filesystem::StepCopyTep>();
+ AddStep<ci::filesystem::StepCreateStorageDirectories>();
+ AddStep<tpk::filesystem::StepCreateSymbolicLink>();
+ AddStep<tpk::filesystem::StepTpkPatchIcons>();
+ AddStep<ci::filesystem::StepCreateIcons>();
+ AddStep<ci::security::StepRegisterSecurity>();
+ AddStep<tpk::pkgmgr::StepConvertXml>();
+ AddStep<tpk::pkgmgr::StepManifestAdjustment>();
+ AddStep<ci::pkgmgr::StepRegisterApplication>();
+ AddStep<ci::pkgmgr::StepRunParserPlugin>(
+ ci::Plugin::ActionType::Install);
+ AddStep<ci::filesystem::StepCreatePerUserStorageDirectories>();
+}
+
+void TpkInstaller::MountUpdateSteps() {
+ AddStep<ci::configuration::StepConfigure>(pkgmgr_);
+ AddStep<ci::mount::StepMountUnpacked>();
+ AddStep<ci::configuration::StepParseManifest>(
+ ci::configuration::StepParseManifest::ManifestLocation::PACKAGE,
+ ci::configuration::StepParseManifest::StoreLocation::NORMAL);
+ AddStep<tpk::configuration::StepParsePreload>();
+ AddStep<ci::pkgmgr::StepCheckBlacklist>();
+ AddStep<ci::security::StepCheckSignature>();
+ AddStep<ci::security::StepPrivilegeCompatibility>();
+ AddStep<tpk::security::StepCheckTpkBackgroundCategory>();
+ AddStep<ci::security::StepCheckOldCertificate>();
+ AddStep<ci::configuration::StepParseManifest>(
+ ci::configuration::StepParseManifest::ManifestLocation::INSTALLED,
+ ci::configuration::StepParseManifest::StoreLocation::BACKUP);
+ AddStep<ci::configuration::StepBlockCrossUpdate>();
+ AddStep<ci::pkgmgr::StepKillApps>();
+ AddStep<ci::backup::StepBackupManifest>();
+ AddStep<ci::backup::StepBackupIcons>();
+ AddStep<ci::mount::StepMountUpdate>();
+ AddStep<tpk::filesystem::StepTpkPreparePackageDirectory>();
+ AddStep<ci::filesystem::StepCopyTep>();
+ AddStep<ci::pkgmgr::StepUpdateTep>();
+ AddStep<tpk::filesystem::StepCreateSymbolicLink>();
+ AddStep<tpk::filesystem::StepTpkPatchIcons>();
+ AddStep<ci::filesystem::StepCreateIcons>();
+ AddStep<ci::security::StepUpdateSecurity>();
+ AddStep<tpk::pkgmgr::StepConvertXml>();
+ AddStep<tpk::pkgmgr::StepManifestAdjustment>();
+ AddStep<ci::pkgmgr::StepUpdateApplication>();
+ AddStep<ci::pkgmgr::StepRunParserPlugin>(ci::Plugin::ActionType::Upgrade);
+}
+
void TpkInstaller::ManifestDirectInstallSteps() {
AddStep<ci::configuration::StepConfigure>(pkgmgr_);
AddStep<tpk::filesystem::StepCheckPkgDirPath>();
void ReinstallSteps();
void DeltaSteps();
void RecoverySteps();
+ void MountInstallSteps();
+ void MountUpdateSteps();
void ManifestDirectInstallSteps();
void ManifestDirectUpdateSteps();
void ClearSteps();