Fix static analysis issue
[platform/core/appfw/app-installers.git] / src / pkg_recovery / pkg_recovery.cc
index 0a8d80f..266748c 100644 (file)
@@ -7,13 +7,15 @@
 #include <boost/filesystem/path.hpp>
 
 #include <glib.h>
-#include <common/request.h>
+#include <common/utils/file_util.h>
+#include <common/utils/request.h>
 #include <common/utils/subprocess.h>
 #include <common/utils/user_util.h>
 #include <manifest_parser/utils/logging.h>
 #include <sys/types.h>
 #include <tzplatform_config.h>
 
+#include <array>
 #include <regex>
 #include <string>
 #include <vector>
@@ -26,9 +28,43 @@ namespace {
 typedef std::pair<std::string, std::string> RecoverEntry;
 
 const char kRecoveryFilePattern[] = "^(.*)-recovery-(.){6}$";
-const char kBackupFilePattern[] = "^(.*)-recovery-(.){6}\.bck$";
+const char kBackupFilePattern[] = "^(.*)-recovery-(.){6}\\.bck$";
 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
 
+std::string TruncateNewLine(const char* data) {
+  int length = strlen(data);
+  if (data[length - 1] == '\n')
+      --length;
+  return std::string(data, length);
+}
+
+std::vector<std::string> ParseRecoveryFile(const char* file) {
+  FILE* handle = fopen(file, "r");
+  if (!handle) {
+    LOG(ERROR) << "Failed to open recovery file :" << file;
+    return {};
+  }
+
+  std::vector<std::string> arguments;
+  std::array<char, 200> data;
+  data[0] = '\0';
+  while (fgets(data.data(), data.size(), handle)) {
+    std::string line_data = TruncateNewLine(data.data());
+    if (line_data == "cleanup") {
+      arguments.emplace_back("--recovery-cleanup");
+      break;
+    }
+
+    if (!boost::filesystem::exists(line_data))
+      continue;
+
+    arguments.emplace_back(line_data);
+  }
+  fclose(handle);
+
+  return arguments;
+}
+
 class PkgRecoveryService {
  public:
   PkgRecoveryService();
@@ -53,10 +89,25 @@ bool PkgRecoveryService::RunBackend(uid_t uid, const char* type,
   std::string backend_cmd = "/usr/bin/" + std::string(type) + "-backend";
   ci::Subprocess backend(backend_cmd);
   std::string str_uid = std::to_string(uid);
-  backend.Run("-b", file, "-u", str_uid.c_str());
+  if (std::string(type) == "unified") {
+    auto arguments = ParseRecoveryFile(file);
+    if (!arguments.size())
+      return ci::Remove(bf::path(file));
+
+    arguments.emplace(arguments.begin(), "-b");
+    arguments.emplace_back("-u");
+    arguments.emplace_back(str_uid.c_str());
+
+    backend.RunWithArgs(arguments);
+  } else {
+    backend.Run("-b", file, "-u", str_uid.c_str());
+  }
   int status = backend.Wait();
   if (WIFSIGNALED(status) || WEXITSTATUS(status))
     return false;
+
+  ci::Remove(bf::path(file));
+
   return true;
 }
 
@@ -69,7 +120,7 @@ void PkgRecoveryService::Run() {
 
   // recover normal user packages
   ci::UserList list = ci::GetUserList();
-  for (auto userinfo : list) {
+  for (const auto& userinfo : list) {
     uid_t uid = std::get<0>(userinfo);
     LOG(INFO) << "Searching recovery files for user " << std::get<0>(userinfo);
     SearchBackupFiles(uid);
@@ -80,25 +131,23 @@ void PkgRecoveryService::Run() {
 
 void PkgRecoveryService::SearchBackupFiles(uid_t uid) {
   const bf::path recovery_dir = ci::GetRootAppPath(false, uid);
-  for (bf::directory_iterator iter(recovery_dir);
-      iter != bf::directory_iterator();
-      ++iter) {
-    try {
+  try {
+    for (bf::directory_iterator iter(recovery_dir);
+        iter != bf::directory_iterator();
+        ++iter) {
       std::string file = iter->path().filename().string();
       std::regex backup_regex(kBackupFilePattern);
       std::smatch match;
       if (std::regex_search(file, match, backup_regex)) {
         bf::path orig_file(iter->path().parent_path() / iter->path().stem());
         if (bf::exists(orig_file))
-          bf::remove(iter->path());
-        else
-          bf::rename(iter->path(), orig_file);
+          bf::remove(orig_file);
+        bf::rename(iter->path(), orig_file);
       }
-    } catch (...) {
-      LOG(WARNING) << "Exception occurred: "
-                   << boost::current_exception_diagnostic_information();
-      continue;
     }
+  } catch (...) {
+    LOG(WARNING) << "Exception occurred: "
+                 << boost::current_exception_diagnostic_information();
   }
 }
 
@@ -116,7 +165,10 @@ std::vector<RecoverEntry> PkgRecoveryService::SearchRecoveryFiles(uid_t uid) {
       if (std::regex_search(file, match, recovery_regex)) {
         LOG(INFO) << "Found recovery file: " << file;
         std::string type(match[1]);
-        list.emplace_back(type, iter->path().string());
+        if (type == "unified")
+          list.emplace(list.begin(), type, iter->path().string());
+        else
+          list.emplace_back(type, iter->path().string());
       }
     } catch (...) {
       LOG(WARNING) << "Exception occurred: "
@@ -131,9 +183,12 @@ std::vector<RecoverEntry> PkgRecoveryService::SearchRecoveryFiles(uid_t uid) {
 void PkgRecoveryService::ProcessRecovery(uid_t uid,
     const std::vector<RecoverEntry>& entries) {
   LOG(INFO) << "Process recovery for user " << uid;
-  for (auto entry : entries) {
+  for (const auto& entry : entries) {
     const char* type = entry.first.c_str();
     const char* file = entry.second.c_str();
+    if (!bf::exists(file))
+      continue;
+
     if (!RunBackend(uid, type, file))
       LOG(ERROR) << "Recovery process for " << file << " failed";
   }
@@ -142,7 +197,12 @@ void PkgRecoveryService::ProcessRecovery(uid_t uid,
 }  // namespace
 
 int main() {
-  PkgRecoveryService service;
-  service.Run();
-  return 0;
+  try {
+    PkgRecoveryService service;
+    service.Run();
+    return 0;
+  } catch(...) {
+    LOG(ERROR) << "Exception occured";
+    return -1;
+  }
 }