Skip the security registration if it is unnecessary
[platform/core/appfw/app-installers.git] / src / common / recovery_file.cc
index 22f2671..ace2414 100644 (file)
@@ -5,34 +5,51 @@
 #include "common/recovery_file.h"
 
 #include <boost/filesystem/operations.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
 #include <boost/system/error_code.hpp>
 
+#include <manifest_parser/utils/logging.h>
+
 #include <array>
 #include <cstring>
+#include <string>
 #include <map>
+#include <utility>
 
 #include "common/installer_context.h"
-#include "common/utils/logging.h"
+#include "common/utils/file_util.h"
 
 namespace bf = boost::filesystem;
 namespace bs = boost::system;
+namespace bi = boost::iostreams;
 namespace ci = common_installer;
 
 namespace {
 
-const char kRecoveryNewInstallationString[] = "NEW";
-const char kRecoveryUpdateInstallationString[] = "UPDATE";
-const char kRecoveryUninstallationString[] = "UNINSTALLATION";
+const char kRecoveryInstallString[] = "NEW";
+const char kRecoveryUpdateString[] = "UPDATE";
+const char kRecoveryUninstallationString[] = "UNINSTALL";
 const char kRecoveryRdsString[] = "RDS";
 const char kRecoveryDeltaString[] = "DELTA";
+const char kRecoveryMountInstallString[] = "MOUNTINSTALL";
+const char kRecoveryMountUpdateString[] = "MOUNTUPDATE";
+const char kRecoveryReadonlyUpdateInstallString[] = "READONLYUPDATEINSTALL";
+const char kRecoveryReadonlyUpdateUninstallString[] = "READONLYUPDATEUNINSTALL";
 const char kRecoveryUnknownString[] = "UNKNOWN";
 
 const std::map<std::string, ci::RequestType> kStringToRequestMap = {
-  {kRecoveryNewInstallationString, ci::RequestType::Install},
-  {kRecoveryUpdateInstallationString, ci::RequestType::Update},
+  {kRecoveryInstallString, ci::RequestType::Install},
+  {kRecoveryUpdateString, ci::RequestType::Update},
   {kRecoveryUninstallationString, ci::RequestType::Uninstall},
   {kRecoveryRdsString, ci::RequestType::Reinstall},
-  {kRecoveryDeltaString, ci::RequestType::Delta}
+  {kRecoveryDeltaString, ci::RequestType::Delta},
+  {kRecoveryMountInstallString, ci::RequestType::MountInstall},
+  {kRecoveryMountUpdateString, ci::RequestType::MountUpdate},
+  {kRecoveryReadonlyUpdateInstallString,
+      ci::RequestType::ReadonlyUpdateInstall},
+  {kRecoveryReadonlyUpdateUninstallString,
+      ci::RequestType::ReadonlyUpdateUninstall},
 };
 
 std::string TruncateNewLine(const char* data) {
@@ -47,13 +64,13 @@ std::string TruncateNewLine(const char* data) {
 namespace common_installer {
 namespace recovery {
 
-std::unique_ptr<RecoveryFile> RecoveryFile::CreateRecoveryFileForPath(
-    const boost::filesystem::path& path) {
+std::unique_ptr<RecoveryFile> RecoveryFile::CreateRecoveryFile(
+    const boost::filesystem::path& path, RequestType type) {
   if (bf::exists(path)) {
     LOG(ERROR) << "Recovery file already exists!";
     return nullptr;
   }
-  std::unique_ptr<RecoveryFile> file(new RecoveryFile(path, false));
+  std::unique_ptr<RecoveryFile> file(new RecoveryFile(path, type, false));
   if (file->is_detached()) {
     LOG(ERROR) << "Failed to access file";
     return nullptr;
@@ -61,13 +78,14 @@ std::unique_ptr<RecoveryFile> RecoveryFile::CreateRecoveryFileForPath(
   return file;
 }
 
-std::unique_ptr<RecoveryFile> RecoveryFile::OpenRecoveryFileForPath(
+std::unique_ptr<RecoveryFile> RecoveryFile::OpenRecoveryFile(
     const boost::filesystem::path& path) {
   if (!bf::exists(path)) {
     LOG(ERROR) << "Cannot open recovery file";
     return nullptr;
   }
-  std::unique_ptr<RecoveryFile> file(new RecoveryFile(path, true));
+  std::unique_ptr<RecoveryFile> file(new RecoveryFile(path,
+      RequestType::Unknown, true));
   if (file->is_detached()) {
     LOG(ERROR) << "Failed to read recovery file";
     return nullptr;
@@ -75,8 +93,10 @@ std::unique_ptr<RecoveryFile> RecoveryFile::OpenRecoveryFileForPath(
   return file;
 }
 
-RecoveryFile::RecoveryFile(const bf::path& path, bool load)
-    : path_(path) {
+RecoveryFile::RecoveryFile(const bf::path& path, RequestType type, bool load)
+    : type_(type), path_(path), backup_done_(false), cleanup_(false),
+      security_operation_done_(false) {
+  backup_path_ = path_.string() + ".bck";
   if (load) {
     if (!ReadFileContent()) {
       path_.clear();
@@ -84,22 +104,19 @@ RecoveryFile::RecoveryFile(const bf::path& path, bool load)
     }
   } else {
     // create file
-    FILE* handle = fopen(path.c_str(), "w");
-    if (!handle) {
+    if (!WriteAndCommitFileContent()) {
       path_.clear();
       return;
     }
-    fclose(handle);
     LOG(DEBUG) << "Recovery file " << path_ << " created";
   }
 }
 
 RecoveryFile::~RecoveryFile() {
-  if (!path_.empty()) {
-    bs::error_code error;
-    bf::remove(path_, error);
+  if (Remove(path_))
     LOG(DEBUG) << "Recovery file " << path_ << " removed";
-  }
+  if (Remove(backup_path_))
+    LOG(DEBUG) << "Recovery file " << backup_path_ << " removed";
 }
 
 void RecoveryFile::Detach() {
@@ -111,16 +128,25 @@ bool RecoveryFile::is_detached() const {
 }
 
 void RecoveryFile::set_unpacked_dir(
-    const boost::filesystem::path& unpacked_dir) {
-  unpacked_dir_ = unpacked_dir;
+    boost::filesystem::path unpacked_dir) {
+  unpacked_dir_ = std::move(unpacked_dir);
+}
+
+void RecoveryFile::set_pkgid(std::string pkgid) {
+  pkgid_ = std::move(pkgid);
+}
+
+
+void RecoveryFile::set_backup_done(bool backup_done) {
+  backup_done_ = backup_done;
 }
 
-void RecoveryFile::set_pkgid(const std::string& pkgid) {
-  pkgid_ = pkgid;
+void RecoveryFile::set_cleanup(bool cleanup) {
+  cleanup_ = cleanup;
 }
 
-void RecoveryFile::set_type(RequestType type) {
-  type_ = type;
+void RecoveryFile::set_security_operation_done(bool security_operation_done) {
+  security_operation_done_ = security_operation_done;
 }
 
 const boost::filesystem::path& RecoveryFile::unpacked_dir() const {
@@ -135,6 +161,18 @@ RequestType RecoveryFile::type() const {
   return type_;
 }
 
+bool RecoveryFile::backup_done() const {
+  return backup_done_;
+}
+
+bool RecoveryFile::cleanup() const {
+  return cleanup_;
+}
+
+bool RecoveryFile::security_operation_done() const {
+  return security_operation_done_;
+}
+
 bool RecoveryFile::ReadFileContent() {
   FILE* handle = fopen(path_.c_str(), "r");
   if (!handle) {
@@ -166,42 +204,96 @@ bool RecoveryFile::ReadFileContent() {
     return true;
   }
   pkgid_ = TruncateNewLine(data.data());
+  if (!fgets(data.data(), data.size(), handle)) {
+    fclose(handle);
+    return true;
+  }
+  std::string backup_flag = TruncateNewLine(data.data());
+  if (backup_flag == "true")
+    backup_done_ = true;
+  else
+    backup_done_ = false;
+  if (!fgets(data.data(), data.size(), handle)) {
+    fclose(handle);
+    return true;
+  }
+  std::string cleanup_flag = TruncateNewLine(data.data());
+  if (cleanup_flag == "cleanup")
+    cleanup_ = true;
+  else
+    cleanup_ = false;
+  if (!fgets(data.data(), data.size(), handle)) {
+    fclose(handle);
+    return true;
+  }
+  std::string security_operation_done_flag = TruncateNewLine(data.data());
+  if (security_operation_done_flag == "true")
+    security_operation_done_ = true;
+  else
+    security_operation_done_ = false;
   fclose(handle);
   return true;
 }
 
 bool RecoveryFile::WriteAndCommitFileContent() {
-  FILE* handle = fopen(path_.c_str(), "w");
-  if (!handle) {
+  if (bf::exists(path_))  {
+    bs::error_code error;
+    bf::rename(path_, backup_path_, error);
+    if (error) {
+      LOG(ERROR) << "Cannot backup recovery file:" << path_ <<
+          ", error: " << error;
+      return false;
+    }
+  }
+
+  bi::stream<bi::file_descriptor_sink> ofs(path_);
+  if (!ofs) {
     LOG(ERROR) << "Cannot write recovery file";
     return false;
   }
+
   switch (type_) {
   case RequestType::Install:
-    fputs(kRecoveryNewInstallationString, handle);
+    ofs << kRecoveryInstallString << std::endl;
     break;
   case RequestType::Update:
-    fputs(kRecoveryUpdateInstallationString, handle);
+    ofs << kRecoveryUpdateString << std::endl;
     break;
   case RequestType::Uninstall:
-    fputs(kRecoveryUninstallationString, handle);
+    ofs << kRecoveryUninstallationString << std::endl;
     break;
   case RequestType::Reinstall:
-    fputs(kRecoveryRdsString, handle);
+    ofs << kRecoveryRdsString << std::endl;
     break;
   case RequestType::Delta:
-    fputs(kRecoveryDeltaString, handle);
+    ofs << kRecoveryDeltaString << std::endl;
+    break;
+  case RequestType::MountInstall:
+    ofs << kRecoveryMountInstallString << std::endl;
+    break;
+  case RequestType::MountUpdate:
+    ofs << kRecoveryMountUpdateString << std::endl;
+    break;
+  case RequestType::ReadonlyUpdateInstall:
+    ofs << kRecoveryReadonlyUpdateInstallString << std::endl;
+    break;
+  case RequestType::ReadonlyUpdateUninstall:
+    ofs << kRecoveryReadonlyUpdateUninstallString << std::endl;
     break;
   default:
-    fputs(kRecoveryUnknownString, handle);
+    ofs << kRecoveryUnknownString << std::endl;
     break;
   }
-  fputs("\n", handle);
-  fputs(unpacked_dir_.c_str(), handle);
-  fputs("\n", handle);
-  fputs(pkgid_.c_str(), handle);
-  fputs("\n", handle);
-  fclose(handle);
+  ofs << unpacked_dir_.c_str() << std::endl;
+  ofs << pkgid_ << std::endl;
+  ofs << (backup_done_ ? "true" : "false") << std::endl;
+  ofs << (cleanup_ ? "cleanup" : "rollback") << std::endl;
+  ofs << (security_operation_done_ ? "true" : "false") << std::endl;
+  ofs.flush();
+  ::fsync(ofs->handle());
+  ofs.close();
+
+  Remove(backup_path_);
   return true;
 }