Mount install steps 58/65758/9 accepted/tizen/common/20160505.140336 accepted/tizen/ivi/20160506.035727 accepted/tizen/mobile/20160506.035145 accepted/tizen/tv/20160506.035519 accepted/tizen/wearable/20160506.035618 submit/tizen/20160504.074553
authorTomasz Iwanek <t.iwanek@samsung.com>
Mon, 11 Apr 2016 12:41:17 +0000 (14:41 +0200)
committerTomasz Iwanek <t.iwanek@samsung.com>
Tue, 26 Apr 2016 13:39:34 +0000 (15:39 +0200)
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

src/tpk/CMakeLists.txt
src/tpk/step/filesystem/step_tpk_prepare_package_directory.cc [new file with mode: 0644]
src/tpk/step/filesystem/step_tpk_prepare_package_directory.h [new file with mode: 0644]
src/tpk/step/filesystem/step_tpk_update_package_directory.cc [new file with mode: 0644]
src/tpk/step/filesystem/step_tpk_update_package_directory.h [new file with mode: 0644]
src/tpk/tpk_app_query_interface.cc
src/tpk/tpk_installer.cc
src/tpk/tpk_installer.h

index e562860..8f32968 100644 (file)
@@ -3,6 +3,8 @@ SET(SRCS
   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
diff --git a/src/tpk/step/filesystem/step_tpk_prepare_package_directory.cc b/src/tpk/step/filesystem/step_tpk_prepare_package_directory.cc
new file mode 100644 (file)
index 0000000..7297cad
--- /dev/null
@@ -0,0 +1,142 @@
+// 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
diff --git a/src/tpk/step/filesystem/step_tpk_prepare_package_directory.h b/src/tpk/step/filesystem/step_tpk_prepare_package_directory.h
new file mode 100644 (file)
index 0000000..059feb1
--- /dev/null
@@ -0,0 +1,64 @@
+// 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_
diff --git a/src/tpk/step/filesystem/step_tpk_update_package_directory.cc b/src/tpk/step/filesystem/step_tpk_update_package_directory.cc
new file mode 100644 (file)
index 0000000..835e1cd
--- /dev/null
@@ -0,0 +1,114 @@
+// 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
diff --git a/src/tpk/step/filesystem/step_tpk_update_package_directory.h b/src/tpk/step/filesystem/step_tpk_update_package_directory.h
new file mode 100644 (file)
index 0000000..a0fe215
--- /dev/null
@@ -0,0 +1,46 @@
+// 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_
index b1e1568..0afa379 100644 (file)
@@ -34,7 +34,7 @@ const char kManifestFileName[] = "tizen-manifest.xml";
 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;
index 310ff96..a101357 100644 (file)
@@ -5,6 +5,7 @@
 #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"
@@ -94,6 +101,12 @@ void TpkInstaller::Prepare() {
     case ci::RequestType::Recovery:
       RecoverySteps();
       break;
+    case ci::RequestType::MountInstall:
+      MountInstallSteps();
+      break;
+    case ci::RequestType::MountUpdate:
+      MountUpdateSteps();
+      break;
     case ci::RequestType::ManifestDirectInstall:
       ManifestDirectInstallSteps();
       break;
@@ -151,6 +164,7 @@ void TpkInstaller::UpdateSteps() {
   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>();
@@ -181,6 +195,7 @@ void TpkInstaller::UninstallSteps() {
   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>();
@@ -202,6 +217,7 @@ void TpkInstaller::ReinstallSteps() {
   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>();
@@ -232,6 +248,7 @@ void TpkInstaller::DeltaSteps() {
   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>();
@@ -261,6 +278,67 @@ void TpkInstaller::RecoverySteps() {
   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>();
index 8037f81..44c0545 100644 (file)
@@ -30,6 +30,8 @@ class TpkInstaller : public common_installer::AppInstaller {
   void ReinstallSteps();
   void DeltaSteps();
   void RecoverySteps();
+  void MountInstallSteps();
+  void MountUpdateSteps();
   void ManifestDirectInstallSteps();
   void ManifestDirectUpdateSteps();
   void ClearSteps();