Fix StepDeltaPatch and ExternalMount 77/80277/5
authorTomasz Iwanek <t.iwanek@samsung.com>
Fri, 15 Jul 2016 08:41:54 +0000 (10:41 +0200)
committerTomasz Iwanek <t.iwanek@samsung.com>
Fri, 22 Jul 2016 13:29:55 +0000 (15:29 +0200)
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
src/common/external_mount.cc [new file with mode: 0644]
src/common/external_mount.h [new file with mode: 0644]
src/common/external_storage.cc
src/common/external_storage.h
src/common/installer_context.h
src/common/step/filesystem/step_delta_patch.cc
src/common/step/filesystem/step_disable_external_mount.cc [new file with mode: 0644]
src/common/step/filesystem/step_disable_external_mount.h [new file with mode: 0644]
src/common/step/filesystem/step_enable_external_mount.cc [new file with mode: 0644]
src/common/step/filesystem/step_enable_external_mount.h [new file with mode: 0644]

index 98b3959..dac9a07 100644 (file)
@@ -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 (file)
index 0000000..8762629
--- /dev/null
@@ -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 <app2ext_interface.h>
+#include <manifest_parser/utils/logging.h>
+
+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 (file)
index 0000000..d37ddc9
--- /dev/null
@@ -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 <unistd.h>
+
+#include <string>
+
+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_
index a35bdc3..2ea3584 100644 (file)
@@ -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<app2ext_move_type_t>(move_type_),
                                uid_);
     break;
-  }
   default:
     assert(false && "Not supported installation mode");
   }
index 05d7f4f..ae8f7cb 100644 (file)
 
 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<ExternalStorage> MoveInstalledStorage(
index 2cafbec..e448c67 100644 (file)
@@ -19,6 +19,7 @@
 #include <utility>
 #include <vector>
 
+#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<ExternalStorage> external_storage;
+
+  /**
+   * @brief External package mount object if delta update with external
+   */
+  std::unique_ptr<ExternalMount> external_mount;
 };
 
 }  // namespace common_installer
index d454354..bd28b7f 100644 (file)
@@ -12,6 +12,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <algorithm>
 #include <cstdlib>
 
 #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 (file)
index 0000000..f135f00
--- /dev/null
@@ -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 (file)
index 0000000..74d7bbc
--- /dev/null
@@ -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 <manifest_parser/utils/logging.h>
+
+#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 (file)
index 0000000..13c2489
--- /dev/null
@@ -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<ExternalMount> 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 (file)
index 0000000..3b30c18
--- /dev/null
@@ -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 <manifest_parser/utils/logging.h>
+
+#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_