72babe0c61b16c313cc616c2a03566e6bcfee28e
[platform/core/appfw/app-installers.git] / src / pkg_recovery / pkg_recovery.cc
1 // Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache-2.0 license that can be
3 // found in the LICENSE file.
4
5 #include <boost/exception/diagnostic_information.hpp>
6 #include <boost/filesystem/operations.hpp>
7 #include <boost/filesystem/path.hpp>
8
9 #include <glib.h>
10 #include <common/request.h>
11 #include <common/utils/subprocess.h>
12 #include <common/utils/user_util.h>
13 #include <manifest_parser/utils/logging.h>
14 #include <sys/types.h>
15 #include <tzplatform_config.h>
16
17 #include <regex>
18 #include <string>
19 #include <vector>
20
21 namespace bf = boost::filesystem;
22 namespace ci = common_installer;
23
24 namespace {
25
26 typedef std::pair<std::string, std::string> RecoverEntry;
27
28 const char kRecoveryFilePattern[] = "^(.*)-recovery-(.){6}$";
29 const char kBackupFilePattern[] = "^(.*)-recovery-(.){6}\\.bck$";
30 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
31
32 class PkgRecoveryService {
33  public:
34   PkgRecoveryService();
35   ~PkgRecoveryService();
36   void Run();
37
38  private:
39   void SearchBackupFiles(uid_t uid);
40   std::vector<RecoverEntry> SearchRecoveryFiles(uid_t uid);
41   void ProcessRecovery(uid_t uid, const std::vector<RecoverEntry>& entries);
42   bool RunBackend(uid_t uid, const char* type, const char* file);
43 };
44
45 PkgRecoveryService::PkgRecoveryService() {
46 }
47
48 PkgRecoveryService::~PkgRecoveryService() {
49 }
50
51 bool PkgRecoveryService::RunBackend(uid_t uid, const char* type,
52     const char* file) {
53   std::string backend_cmd = "/usr/bin/" + std::string(type) + "-backend";
54   ci::Subprocess backend(backend_cmd);
55   std::string str_uid = std::to_string(uid);
56   backend.Run("-b", file, "-u", str_uid.c_str());
57   int status = backend.Wait();
58   if (WIFSIGNALED(status) || WEXITSTATUS(status))
59     return false;
60   return true;
61 }
62
63 void PkgRecoveryService::Run() {
64   // recover global packages
65   SearchBackupFiles(kGlobalUserUid);
66   LOG(INFO) << "Searching recovery files for user " << kGlobalUserUid;
67   std::vector<RecoverEntry> globalentries = SearchRecoveryFiles(kGlobalUserUid);
68   ProcessRecovery(kGlobalUserUid, globalentries);
69
70   // recover normal user packages
71   ci::UserList list = ci::GetUserList();
72   for (auto userinfo : list) {
73     uid_t uid = std::get<0>(userinfo);
74     LOG(INFO) << "Searching recovery files for user " << std::get<0>(userinfo);
75     SearchBackupFiles(uid);
76     std::vector<RecoverEntry> entries = SearchRecoveryFiles(uid);
77     ProcessRecovery(uid, entries);
78   }
79 }
80
81 void PkgRecoveryService::SearchBackupFiles(uid_t uid) {
82   const bf::path recovery_dir = ci::GetRootAppPath(false, uid);
83   for (bf::directory_iterator iter(recovery_dir);
84       iter != bf::directory_iterator();
85       ++iter) {
86     try {
87       std::string file = iter->path().filename().string();
88       std::regex backup_regex(kBackupFilePattern);
89       std::smatch match;
90       if (std::regex_search(file, match, backup_regex)) {
91         bf::path orig_file(iter->path().parent_path() / iter->path().stem());
92         if (bf::exists(orig_file))
93           bf::remove(iter->path());
94         else
95           bf::rename(iter->path(), orig_file);
96       }
97     } catch (...) {
98       LOG(WARNING) << "Exception occurred: "
99                    << boost::current_exception_diagnostic_information();
100       continue;
101     }
102   }
103 }
104
105 std::vector<RecoverEntry> PkgRecoveryService::SearchRecoveryFiles(uid_t uid) {
106   std::vector<RecoverEntry> list;
107   const bf::path recovery_dir = ci::GetRootAppPath(false, uid);
108   LOG(INFO) << "RootAppPath: " << recovery_dir;
109   for (bf::directory_iterator iter(recovery_dir);
110       iter != bf::directory_iterator();
111       ++iter) {
112     try {
113       std::string file = iter->path().filename().string();
114       std::regex recovery_regex(kRecoveryFilePattern);
115       std::smatch match;
116       if (std::regex_search(file, match, recovery_regex)) {
117         LOG(INFO) << "Found recovery file: " << file;
118         std::string type(match[1]);
119         list.emplace_back(type, iter->path().string());
120       }
121     } catch (...) {
122       LOG(WARNING) << "Exception occurred: "
123                    << boost::current_exception_diagnostic_information();
124       continue;
125     }
126   }
127
128   return list;
129 }
130
131 void PkgRecoveryService::ProcessRecovery(uid_t uid,
132     const std::vector<RecoverEntry>& entries) {
133   LOG(INFO) << "Process recovery for user " << uid;
134   for (auto entry : entries) {
135     const char* type = entry.first.c_str();
136     const char* file = entry.second.c_str();
137     if (!RunBackend(uid, type, file))
138       LOG(ERROR) << "Recovery process for " << file << " failed";
139   }
140 }
141
142 }  // namespace
143
144 int main() {
145   PkgRecoveryService service;
146   service.Run();
147   return 0;
148 }