Fix StepUpdateStorageDirectories 22/218222/16
authorSangyoon Jang <jeremy.jang@samsung.com>
Tue, 19 Nov 2019 04:23:51 +0000 (13:23 +0900)
committerSangyoon Jang <jeremy.jang@samsung.com>
Tue, 3 Dec 2019 12:02:35 +0000 (21:02 +0900)
The step StepUpdateStorageDirectories is for adding / removing
shareddata directory when the package updated with / without privilege
for shareddata. This process can be revoked when the package update is
failed.

Change-Id: Ibef2c65807682bc720f53fe8a3f78d9ca82d3c8c
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
src/common/shared_dirs.cc
src/common/shared_dirs.h
src/common/step/filesystem/step_update_storage_directories.cc
src/common/step/filesystem/step_update_storage_directories.h
src/common/utils/file_util.cc
src/common/utils/file_util.h

index 2fed198..249d8ca 100644 (file)
@@ -371,6 +371,39 @@ bool CreateStorageDirectories(const boost::filesystem::path& root_path,
   return true;
 }
 
+bool BackupSharedDataDirectories(const bf::path& apps_rw,
+    const std::string& pkgid) {
+  if (!ci::MakeBackup(apps_rw / pkgid / kSharedDataDir))
+    return false;
+  if (!ci::MakeBackup(apps_rw / kSharedDir / pkgid / kData))
+    return false;
+  if (!ci::MakeBackup(apps_rw / kSharedTmpDir / pkgid))
+    return false;
+  return true;
+}
+
+bool RestoreSharedDataDirectories(const bf::path& apps_rw,
+    const std::string& pkgid) {
+  if (!ci::RestoreBackup(apps_rw / pkgid / kSharedDataDir))
+    return false;
+  if (!ci::RestoreBackup(apps_rw / kSharedDir / pkgid / kData))
+    return false;
+  if (!ci::RestoreBackup(apps_rw / kSharedTmpDir / pkgid))
+    return false;
+  return true;
+}
+
+bool RemoveBackupSharedDataDirectories(const bf::path& apps_rw,
+    const std::string& pkgid) {
+  if (!ci::RemoveBackup(apps_rw / pkgid / kSharedDataDir))
+    return false;
+  if (!ci::RemoveBackup(apps_rw / kSharedDir / pkgid / kData))
+    return false;
+  if (!ci::RemoveBackup(apps_rw / kSharedTmpDir / pkgid))
+    return false;
+  return true;
+}
+
 }  // namespace
 
 namespace common_installer {
@@ -570,33 +603,6 @@ bool CreateSkelDirectories(const std::string& pkgid,
   return result;
 }
 
-bool UpdateSkelDirectories(const std::string& pkgid,
-                           bool is_remove_shareddata) {
-  bf::path root_path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
-                       bf::path(kSkelAppDir);
-  LOG(DEBUG) << ((is_remove_shareddata) ? "Removing" : "Creating")
-             << " skel directory for pkgid: " << pkgid;
-  if (is_remove_shareddata) {
-    if (!DeleteSharedDataDirectories(root_path, pkgid))
-      return false;
-    return true;
-  }
-
-  if (!CreateSharedDataDirectories(root_path, pkgid))
-    return false;
-
-  std::string error_message;
-  if (!RegisterSecurityContextForPath(pkgid, root_path / pkgid, kGlobalUserUid,
-                                      false, &error_message)) {
-    LOG(ERROR) << "Failed to register security context for path: "
-               << root_path / pkgid
-               << ", error_message: " << error_message;
-    return false;
-  }
-
-  return true;
-}
-
 bool DeleteSkelDirectories(const std::string& pkgid) {
   bf::path path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
                   bf::path(kSkelAppDir);
@@ -701,62 +707,6 @@ bool CopyUserDirectories(const std::string& pkgid) {
   return true;
 }
 
-bool CreateSharedData(const bf::path& path,
-                      const std::string& pkgid) {
-  return CreateSharedDataDirectories(path, pkgid);
-}
-
-bool UpdateUserDirectory(const std::string& pkgid, bool is_remove_shareddata) {
-  UserList list = ci::GetUserList();
-  for (auto l : list) {
-    bf::path root_path(std::get<2>(l) / "apps_rw");
-    bf::path pkg_path(root_path / pkgid);
-    uid_t uid = std::get<0>(l);
-    LOG(DEBUG) << ((is_remove_shareddata) ? "Deleting" : "Adding")
-               << " shareddata directory for uid: " << uid;
-
-    if (is_remove_shareddata)
-      return DeleteSharedDataDirectories(root_path, pkgid);
-
-    if (!CreateSharedDataDirectories(root_path, pkgid)) {
-      LOG(ERROR) << "Failed to create shared directory: "
-                 << root_path / pkgid;
-      return false;
-    }
-
-    gid_t gid = std::get<1>(l);
-    std::vector<std::string> shared_dirs(kSharedDataEntries);
-    for (auto entry : shared_dirs) {
-      bf::path dst = root_path / entry / pkgid;
-      if (!SetDirectoryOwnerAndPermissions(dst, uid, gid))
-        return false;
-      for (bf::recursive_directory_iterator iter(dst);
-          iter != bf::recursive_directory_iterator(); ++iter) {
-        if (!SetSharedDirOwnerAndPermissions(iter->path(), uid))
-          return false;
-      }
-    }
-
-    if (!SetDirectoryOwnerAndPermissions(pkg_path, uid, gid))
-      return false;
-    for (bf::recursive_directory_iterator iter(pkg_path);
-        iter != bf::recursive_directory_iterator(); ++iter) {
-      if (!SetDirectoryOwnerAndPermissions(iter->path(),
-          uid, gid))
-        return false;
-    }
-
-    std::string error_message;
-    if (!RegisterSecurityContextForPath(pkgid, pkg_path, uid,
-        false, &error_message)) {
-      LOG(ERROR) << "Failed to register security context for path: "
-                  << pkg_path << ", error_message: " << error_message;
-      return false;
-    }
-  }
-  return true;
-}
-
 bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
   if (!bf::exists(src_dir)) {
@@ -894,4 +844,144 @@ bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
     return false;
 }
 
+bool CreateSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  if (!CreateSharedDataDirectories(apps_rw, pkgid))
+    return false;
+
+  bf::path path = apps_rw / pkgid;
+  std::string error_message;
+  if (!ci::RegisterSecurityContextForPath(pkgid, path, uid, false,
+          &error_message)) {
+    LOG(ERROR) << "Failed to register security context for path: " << path
+               << ", error_message: " << error_message;
+    return false;
+  }
+
+  return true;
+}
+
+bool CreatePerUserSharedDataDir(const std::string& pkgid) {
+  // create skel dir
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  LOG(DEBUG) <<  "Creating directory : " << skel_apps_rw;
+  if (!CreateSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  std::string error_message;
+  if (!ci::RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
+          kGlobalUserUid, false, &error_message)) {
+    LOG(ERROR) << "Failed to register security context for path: "
+               << skel_apps_rw / pkgid << ", error_message: " << error_message;
+    return false;
+  }
+
+  // create per user dir
+  ci::UserList list = ci::GetUserList();
+  for (auto l : list) {
+    uid_t uid = std::get<0>(l);
+    LOG(DEBUG) << "Adding shareddata directory for uid: " << uid;
+
+    bf::path apps_rw = ci::GetRootAppPath(false, uid);
+    if (!CreateSharedDataDirectories(apps_rw, pkgid))
+      return false;
+
+    std::string error_message;
+    if (!ci::RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
+        false, &error_message)) {
+      LOG(ERROR) << "Failed to register security context for path: "
+                 << apps_rw / pkgid << ", error_message: " << error_message;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool DeleteSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  return DeleteSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool DeletePerUserSharedDataDir(const std::string& pkgid) {
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!DeleteSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  ci::UserList list = ci::GetUserList();
+  for (auto l : list) {
+    uid_t uid = std::get<0>(l);
+    bf::path apps_rw = ci::GetRootAppPath(false, uid);
+    if (!DeleteSharedDataDirectories(apps_rw, pkgid))
+      return false;
+  }
+
+  return true;
+}
+
+bool BackupSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  return BackupSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool BackupPerUserSharedDataDir(const std::string& pkgid) {
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!BackupSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  ci::UserList list = ci::GetUserList();
+  for (auto l : list) {
+    uid_t uid = std::get<0>(l);
+    if (!BackupSharedDataDir(pkgid, uid))
+      return false;
+  }
+
+  return true;
+}
+
+bool RestoreSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  return RestoreSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool RestorePerUserSharedDataDir(const std::string& pkgid) {
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!RestoreSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  ci::UserList list = ci::GetUserList();
+  for (auto l : list) {
+    uid_t uid = std::get<0>(l);
+    if (!RestoreSharedDataDir(pkgid, uid))
+      return false;
+  }
+
+  return true;
+}
+
+bool RemoveBackupSharedDataDir(const std::string& pkgid, uid_t uid) {
+  bf::path apps_rw = ci::GetRootAppPath(false, uid);
+  return RemoveBackupSharedDataDirectories(apps_rw, pkgid);
+}
+
+bool RemoveBackupPerUserSharedDataDir(const std::string& pkgid) {
+  bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
+      bf::path(kSkelAppDir);
+  if (!RemoveBackupSharedDataDirectories(skel_apps_rw, pkgid))
+    return false;
+
+  ci::UserList list = ci::GetUserList();
+  for (auto l : list) {
+    uid_t uid = std::get<0>(l);
+    if (!RemoveBackupSharedDataDir(pkgid, uid))
+      return false;
+  }
+
+  return true;
+}
+
 }  // namespace common_installer
index 5d9a085..b260196 100644 (file)
@@ -128,18 +128,6 @@ bool CreateSkelDirectories(const std::string& pkgid,
 bool DeleteSkelDirectories(const std::string& pkgid);
 
 /**
- * \brief Update skel directory
- *
- * \param pkgid package id
- * \param is_remove_shareddata shared/data directory add/delete flag
- *
- * \return true if succeed, false otherwise
- *
- */
-bool UpdateSkelDirectories(const std::string& pkgid,
-                           bool is_remove_shareddata);
-
-/**
  * \brief Delete per-user directories
  *
  * \param pkgid package id
@@ -160,30 +148,6 @@ bool DeleteUserDirectories(const std::string& pkgid);
 bool CopyUserDirectories(const std::string& pkgid);
 
 /**
- * \brief Update per-user directory
- *
- * \param pkgid package id
- * \param is_remove_shareddata shared/data directory add/delete flag
- *
- * \return true if succeed, false otherwise
- *
- */
-bool UpdateUserDirectory(const std::string& pkgid,
-                           bool is_remove_shareddata);
-
-/**
- * \brief Create shared-data directories
- *
- * \param path root path
- * \param pkgid package id
-  *
- * \return true if succeed, false otherwise
- *
- */
-bool CreateSharedData(const boost::filesystem::path& path,
-                      const std::string& pkgid);
-
-/**
  * \brief Returns path prefix for internal storage, typically '/home'
  *
  * \return path prefix
@@ -261,6 +225,101 @@ bool SetPackageDirectoryOwnerAndPermissions(const boost::filesystem::path& path,
  */
 bool ShouldSupportLegacySharedDataDir(const std::string& api_version);
 
+/**
+ * \brief Creates shared data directory for specific package
+ *
+ * \param pkgid package id
+ * \param uid user id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool CreateSharedDataDir(const std::string& pkgid, uid_t uid);
+
+/**
+ * \brief Creates per user shared data directories for specific package
+ *
+ * \param pkgid package id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool CreatePerUserSharedDataDir(const std::string& pkgid);
+
+/**
+ * \brief Deletes of shared data directory for specific package
+ *
+ * \param pkgid package id
+ * \param uid user id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool DeleteSharedDataDir(const std::string& pkgid, uid_t uid);
+
+/**
+ * \brief Deletes per user shared data directories for specific package
+ *
+ * \param pkgid package id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool DeletePerUserSharedDataDir(const std::string& pkgid);
+
+/**
+ * \brief Backups shared data directories for specific package
+ *
+ * \param pkgid package id
+ * \param uid user id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool BackupSharedDataDir(const std::string& pkgid, uid_t uid);
+
+/**
+ * \brief Backups per user shared data directories for specific package
+ *
+ * \param pkgid package id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool BackupPerUserSharedDataDir(const std::string& pkgid);
+
+/**
+ * \brief Restores shared data directories for specific package
+ *
+ * \param pkgid package id
+ * \param uid user id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool RestoreSharedDataDir(const std::string& pkgid, uid_t uid);
+
+/**
+ * \brief Restores per user shared data directories for specific package
+ *
+ * \param pkgid package id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool RestorePerUserSharedDataDir(const std::string& pkgid);
+
+/**
+ * \brief Removes backup of shared data directories for specific package
+ *
+ * \param pkgid package id
+ * \param uid user id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool RemoveBackupSharedDataDir(const std::string& pkgid, uid_t uid);
+
+/**
+ * \brief Removes backup of per user shared data directories for specific package
+ *
+ * \param pkgid package id
+ *
+ * \return true if succeed, false otherwise
+ */
+bool RemoveBackupPerUserSharedDataDir(const std::string& pkgid);
+
 }  // namespace common_installer
 
 #endif  // COMMON_SHARED_DIRS_H_
index fe56a46..198a146 100644 (file)
 #include <string>
 #include <vector>
 
+#include "common/paths.h"
 #include "common/privileges.h"
+#include "common/security_registration.h"
 #include "common/shared_dirs.h"
 #include "common/utils/file_util.h"
 #include "common/utils/glist_range.h"
+#include "common/utils/user_util.h"
 
 namespace bf = boost::filesystem;
 namespace bs = boost::system;
@@ -22,41 +25,8 @@ namespace ci = common_installer;
 
 namespace {
 
-const char kSharedData[] = "shared/data";
-const char kSkelApp[] = "skel/apps_rw";
-
-bool RemovePerUserSharedDir(const std::string& pkgid) {
-  bf::path shareddir_path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
-      bf::path(kSkelApp) / pkgid / kSharedData;
-  if (!bf::exists(shareddir_path))
-    return true;
-
-  if (!common_installer::UpdateSkelDirectories(pkgid, true)) {
-    LOG(ERROR) << "Failed to remove shared data directory";
-    return false;
-  }
-
-  if (!common_installer::UpdateUserDirectory(pkgid, true)) {
-    LOG(ERROR) << "Failed to remove shared data directory";
-    return false;
-  }
-
-  return true;
-}
-
-bool CreatePerUserSharedDir(const std::string& pkgid) {
-  if (!common_installer::UpdateSkelDirectories(pkgid, false)) {
-    LOG(ERROR) << "Failed to remove shared data directory";
-    return false;
-  }
-
-  if (!common_installer::UpdateUserDirectory(pkgid, false)) {
-    LOG(ERROR) << "Failed to remove shared data directory";
-    return false;
-  }
-
-  return true;
-}
+const char kSharedDataDir[] = "shared/data";
+const char kSkelAppDir[] = "skel/apps_rw";
 
 bool ShouldCreateSharedDataDir(manifest_x* manifest) {
   if (ci::ShouldSupportLegacySharedDataDir(manifest->api_version))
@@ -76,33 +46,79 @@ namespace common_installer {
 namespace filesystem {
 
 bool StepUpdateStorageDirectories::UpdatePerUserStorageDirectories() {
-  manifest_x* manifest = context_->manifest_data.get();
-  if (ShouldCreateSharedDataDir(manifest))
-    return CreatePerUserSharedDir(context_->pkgid.get());
+  if (mode_ == UpdateMode::CREATE)
+    return ci::CreatePerUserSharedDataDir(context_->pkgid.get());
   else
-    return RemovePerUserSharedDir(context_->pkgid.get());
+    return ci::BackupPerUserSharedDataDir(context_->pkgid.get());
 }
 
 bool StepUpdateStorageDirectories::UpdateStorageDirectories() {
-  manifest_x* manifest = context_->manifest_data.get();
-  if (ShouldCreateSharedDataDir(manifest)) {
-    return CreateSharedData(
-        context_->root_application_path.get(), context_->pkgid.get());
-  } else {
-    return DeleteSharedDirectories(
-        context_->root_application_path.get(), context_->pkgid.get());
-  }
+  if (mode_ == UpdateMode::CREATE)
+    return ci::CreateSharedDataDir(context_->pkgid.get(), context_->uid.get());
+  else
+    return ci::BackupSharedDataDir(context_->pkgid.get(), context_->uid.get());
+}
 
-  return true;
+bool StepUpdateStorageDirectories::CleanUpdatePerUserStorageDirectories() {
+  if (mode_ == UpdateMode::CREATE)
+    return true;
+  else
+    return ci::RemoveBackupPerUserSharedDataDir(context_->pkgid.get());
+}
+
+bool StepUpdateStorageDirectories::CleanUpdateStorageDirectories() {
+  if (mode_ == UpdateMode::CREATE)
+    return true;
+  else
+    return ci::RemoveBackupSharedDataDir(context_->pkgid.get(),
+        context_->uid.get());
+}
+
+bool StepUpdateStorageDirectories::UndoUpdatePerUserStorageDirectories() {
+  if (mode_ == UpdateMode::CREATE)
+    return ci::DeletePerUserSharedDataDir(context_->pkgid.get());
+  else
+    return ci::RestorePerUserSharedDataDir(context_->pkgid.get());
+}
+
+bool StepUpdateStorageDirectories::UndoUpdateStorageDirectories() {
+  if (mode_ == UpdateMode::CREATE)
+    return ci::DeleteSharedDataDir(context_->pkgid.get(), context_->uid.get());
+  else
+    return ci::RestoreSharedDataDir(context_->pkgid.get(), context_->uid.get());
 }
 
 Step::Status StepUpdateStorageDirectories::precheck() {
   if (!context_->manifest_data.get())
     return Status::INVALID_VALUE;
+
+  bf::path path;
+  if (context_->request_mode.get() == RequestMode::GLOBAL)
+    path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) / bf::path(kSkelAppDir) /
+        context_->pkgid.get() / kSharedDataDir;
+  else
+    path = bf::path(ci::GetRootAppPath(false, context_->uid.get())) /
+        context_->pkgid.get() / kSharedDataDir;
+
+  bool old_shared_data_exists = bf::exists(path);
+  bool should_create_shared_data = ShouldCreateSharedDataDir(
+      context_->manifest_data.get());
+
+  if ((old_shared_data_exists && should_create_shared_data) ||
+      (!old_shared_data_exists && !should_create_shared_data))
+    mode_ = UpdateMode::NONE;
+  else if (!old_shared_data_exists && should_create_shared_data)
+    mode_ = UpdateMode::CREATE;
+  else
+    mode_ = UpdateMode::DELETE;
+
   return Status::OK;
 }
 
 Step::Status StepUpdateStorageDirectories::process() {
+  if (mode_ == UpdateMode::NONE)
+    return Status::OK;
+
   if (context_->request_mode.get() == RequestMode::GLOBAL) {
     if (!UpdatePerUserStorageDirectories())
       return Status::APP_DIR_ERROR;
@@ -119,5 +135,37 @@ Step::Status StepUpdateStorageDirectories::process() {
   return Status::OK;
 }
 
+Step::Status StepUpdateStorageDirectories::clean() {
+  recovery::RecoveryFile* recovery_file =
+    context_->recovery_info.get().recovery_file.get();
+  recovery_file->set_cleanup(true);
+  recovery_file->WriteAndCommitFileContent();
+  if (mode_ == UpdateMode::NONE)
+    return Status::OK;
+
+  if (context_->request_mode.get() == RequestMode::GLOBAL) {
+    if (!CleanUpdatePerUserStorageDirectories())
+      return Status::APP_DIR_ERROR;
+  } else {
+    if (!CleanUpdateStorageDirectories())
+      return Status::APP_DIR_ERROR;
+  }
+  return Status::OK;
+}
+
+Step::Status StepUpdateStorageDirectories::undo() {
+  if (mode_ == UpdateMode::NONE)
+    return Status::OK;
+
+  if (context_->request_mode.get() == RequestMode::GLOBAL) {
+    if (!UndoUpdatePerUserStorageDirectories())
+      return Status::APP_DIR_ERROR;
+  } else {
+    if (!UndoUpdateStorageDirectories())
+      return Status::APP_DIR_ERROR;
+  }
+  return Status::OK;
+}
+
 }  // namespace filesystem
 }  // namespace common_installer
index cf9907b..2908f3e 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef COMMON_STEP_FILESYSTEM_STEP_UPDATE_STORAGE_DIRECTORIES_H_
 #define COMMON_STEP_FILESYSTEM_STEP_UPDATE_STORAGE_DIRECTORIES_H_
 
+#include <boost/filesystem/path.hpp>
+
 #include <manifest_parser/utils/logging.h>
 
 #include "common/step/step.h"
@@ -17,15 +19,27 @@ class StepUpdateStorageDirectories : public common_installer::Step {
   using Step::Step;
 
   Status process() override;
-  Status clean() override { return Status::OK; }
-  Status undo() override { return Status::OK; }
+  Status clean() override;
+  Status undo() override;
   Status precheck() override;
 
   STEP_NAME(UpdateStorageDirectories)
 
  private:
+  enum class UpdateMode : int {
+    NONE,
+    CREATE,
+    DELETE,
+  };
+
   bool UpdatePerUserStorageDirectories();
   bool UpdateStorageDirectories();
+  bool CleanUpdatePerUserStorageDirectories();
+  bool CleanUpdateStorageDirectories();
+  bool UndoUpdatePerUserStorageDirectories();
+  bool UndoUpdateStorageDirectories();
+
+  UpdateMode mode_;
 };
 
 }  // namespace filesystem
index 1f7f845..0978cd0 100644 (file)
@@ -20,6 +20,7 @@
 #include <string>
 #include <vector>
 
+#include "common/paths.h"
 #include "common/utils/byte_size_literals.h"
 
 namespace ba = boost::algorithm;
@@ -293,6 +294,35 @@ bool CopyFile(const bf::path& src, const bf::path& dst) {
   return true;
 }
 
+bool RestoreBackup(const bf::path& path) {
+  bf::path backup_path = GetBackupPathForPackagePath(path);
+  if (!bf::exists(backup_path) &&
+      !bf::is_symlink(bf::symlink_status(backup_path))) {
+    LOG(WARNING) << backup_path << " does not exist";
+    return true;
+  }
+  return MoveDir(backup_path, path);
+}
+
+bool MakeBackup(const bf::path& path) {
+  if (!bf::exists(path) && !bf::is_symlink(bf::symlink_status(path))) {
+    LOG(WARNING) << path << " does not exist";
+    return true;
+  }
+  bf::path backup_path = GetBackupPathForPackagePath(path);
+  return MoveDir(path, backup_path);
+}
+
+bool RemoveBackup(const bf::path& path) {
+  bf::path backup_path = GetBackupPathForPackagePath(path);
+  if (!bf::exists(backup_path) &&
+      !bf::is_symlink(bf::symlink_status(backup_path))) {
+    LOG(WARNING) << backup_path << " does not exist";
+    return true;
+  }
+  return RemoveAll(backup_path);
+}
+
 bool RemoveAll(const bf::path& path) {
   if (!exists(path))
     return true;
index 20c8a91..19de7f6 100644 (file)
@@ -34,6 +34,12 @@ bool CopyDir(const boost::filesystem::path& src,
 bool CopyFile(const boost::filesystem::path& src,
              const boost::filesystem::path& dst);
 
+bool RestoreBackup(const boost::filesystem::path& path);
+
+bool MakeBackup(const boost::filesystem::path& path);
+
+bool RemoveBackup(const boost::filesystem::path& path);
+
 bool RemoveAll(const boost::filesystem::path& path);
 
 bool Remove(const boost::filesystem::path& path);