Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / global_recovery_file.cc
1 // Copyright (c) 2020 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 "common/global_recovery_file.h"
6
7 #include <manifest_parser/utils/logging.h>
8 #include <unistd.h>
9
10 #include <algorithm>
11 #include <filesystem>
12 #include <string>
13 #include <system_error>
14 #include <vector>
15
16 #include "common/utils/file_util.h"
17 #include "common/pkgmgr_interface.h"
18
19 namespace ci = common_installer;
20 namespace fs = std::filesystem;
21
22 namespace {
23
24 const char kGlobalTypeName[] = "unified";
25
26 fs::path Backup(const fs::path& filepath) {
27   fs::path backup_path(filepath);
28   backup_path += ".bck";
29
30   if (!ci::MoveFile(filepath, backup_path) ||
31       !ci::CopyFile(backup_path, filepath)) {
32     LOG(ERROR) << "Failed to backup";
33     return {};
34   }
35
36   return backup_path;
37 }
38
39 }  // namespace
40
41 namespace common_installer {
42
43 GlobalRecoveryFile::GlobalRecoveryFile(
44     std::shared_ptr<PkgMgrInterface> pkgmgr) : pkgmgr_(pkgmgr) {
45 }
46
47 GlobalRecoveryFile::~GlobalRecoveryFile() {
48   std::error_code ec;
49   if (fs::exists(recovery_filepath_, ec))
50     ci::Remove(recovery_filepath_);
51   if (fs::exists(backup_path_, ec))
52     ci::Remove(backup_path_);
53 }
54
55
56 bool GlobalRecoveryFile::Init() {
57   std::filesystem::path root_path = ci::GetRootAppPath(
58         pkgmgr_->GetIsPreloadRequest(), pkgmgr_->GetUid());
59   recovery_filepath_ = GenerateRecoveryFilePath(root_path, kGlobalTypeName);
60   if (recovery_filepath_.empty())
61       return false;
62
63   return true;
64 }
65
66 std::string GlobalRecoveryFile::AddPathWithType(
67     const std::string& pkg_type) {
68   std::filesystem::path root_path = ci::GetRootAppPath(
69           pkgmgr_->GetIsPreloadRequest(), pkgmgr_->GetUid());
70   fs::path recovery_filepath = GenerateRecoveryFilePath(root_path, pkg_type);
71   if (!AppendString(recovery_filepath.string()))
72     return {};
73
74   recovery_list_.emplace_back(recovery_filepath.string());
75   return recovery_filepath.string();
76 }
77
78 bool GlobalRecoveryFile::AppendPath(
79     const fs::path& additional_path) {
80   return AppendString(additional_path.string());
81 }
82
83 bool GlobalRecoveryFile::AppendCleanUp() {
84   return AppendString("cleanup");
85 }
86
87 bool GlobalRecoveryFile::AppendString(const std::string& val) {
88   if (recovery_filepath_.empty())
89     return true;
90
91   if (fs::exists(recovery_filepath_)) {
92     backup_path_ = Backup(recovery_filepath_);
93     if (backup_path_.empty()) {
94       LOG(ERROR) << "Failed to backup";
95       return false;
96     }
97   }
98
99   FILE* handle = fopen(recovery_filepath_.c_str(), "a");
100   if (!handle) {
101     LOG(ERROR) << "Failed to open file :" << recovery_filepath_;
102     return false;
103   }
104
105   fputs(val.c_str(), handle);
106   fputs("\n", handle);
107   fclose(handle);
108   sync();
109
110   ci::Remove(backup_path_);
111   return true;
112 }
113
114 fs::path GlobalRecoveryFile::GenerateRecoveryFilePath(
115     const fs::path& path, const std::string& type) {
116   fs::path pattern = path;
117   pattern += "/";
118   pattern += type;
119   pattern += "-recovery-%%%%%%";
120   fs::path tmp_path;
121
122   std::vector<std::string>::iterator iter;
123   do {
124     tmp_path = ci::GenerateUniquePathString(pattern);
125     iter = std::find(recovery_list_.begin(), recovery_list_.end(),
126         tmp_path.string());
127   } while (std::filesystem::exists(tmp_path) ||
128       iter != recovery_list_.end());
129
130   return tmp_path;
131 }
132
133 }  // namespace common_installer