1 // Copyright (c) 2015 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.
5 #include "common/recovery_file.h"
7 #include <manifest_parser/utils/logging.h>
13 #include <system_error>
17 #include "common/installer_context.h"
18 #include "common/utils/file_util.h"
20 namespace ci = common_installer;
21 namespace fs = std::filesystem;
25 const char kRecoveryInstallString[] = "NEW";
26 const char kRecoveryUpdateString[] = "UPDATE";
27 const char kRecoveryUninstallationString[] = "UNINSTALL";
28 const char kRecoveryRdsString[] = "RDS";
29 const char kRecoveryDeltaString[] = "DELTA";
30 const char kRecoveryMountInstallString[] = "MOUNTINSTALL";
31 const char kRecoveryMountUpdateString[] = "MOUNTUPDATE";
32 const char kRecoveryReadonlyUpdateInstallString[] = "READONLYUPDATEINSTALL";
33 const char kRecoveryReadonlyUpdateUninstallString[] = "READONLYUPDATEUNINSTALL";
34 const char kRecoveryUnknownString[] = "UNKNOWN";
36 const std::map<std::string, ci::RequestType> kStringToRequestMap = {
37 {kRecoveryInstallString, ci::RequestType::Install},
38 {kRecoveryUpdateString, ci::RequestType::Update},
39 {kRecoveryUninstallationString, ci::RequestType::Uninstall},
40 {kRecoveryRdsString, ci::RequestType::Reinstall},
41 {kRecoveryDeltaString, ci::RequestType::Delta},
42 {kRecoveryMountInstallString, ci::RequestType::MountInstall},
43 {kRecoveryMountUpdateString, ci::RequestType::MountUpdate},
44 {kRecoveryReadonlyUpdateInstallString,
45 ci::RequestType::ReadonlyUpdateInstall},
46 {kRecoveryReadonlyUpdateUninstallString,
47 ci::RequestType::ReadonlyUpdateUninstall},
50 std::string TruncateNewLine(const char* data) {
51 int length = strlen(data);
52 if (data[length - 1] == '\n')
54 return std::string(data, length);
59 namespace common_installer {
62 std::unique_ptr<RecoveryFile> RecoveryFile::CreateRecoveryFile(
63 const std::filesystem::path& path, RequestType type) {
64 if (fs::exists(path)) {
65 LOG(ERROR) << "Recovery file already exists!";
68 std::unique_ptr<RecoveryFile> file(new RecoveryFile(path, type, false));
69 if (file->is_detached()) {
70 LOG(ERROR) << "Failed to access file";
76 std::unique_ptr<RecoveryFile> RecoveryFile::OpenRecoveryFile(
77 const std::filesystem::path& path) {
78 if (!fs::exists(path)) {
79 LOG(ERROR) << "Cannot open recovery file";
82 std::unique_ptr<RecoveryFile> file(new RecoveryFile(path,
83 RequestType::Unknown, true));
84 if (file->is_detached()) {
85 LOG(ERROR) << "Failed to read recovery file";
91 RecoveryFile::RecoveryFile(const fs::path& path, RequestType type, bool load)
92 : type_(type), path_(path), backup_done_(false), cleanup_(false),
93 security_operation_done_(false) {
94 backup_path_ = path_.string() + ".bck";
96 if (!ReadFileContent()) {
102 if (!WriteAndCommitFileContent()) {
106 LOG(DEBUG) << "Recovery file " << path_ << " created";
110 RecoveryFile::~RecoveryFile() {
112 LOG(DEBUG) << "Recovery file " << path_ << " removed";
113 if (Remove(backup_path_))
114 LOG(DEBUG) << "Recovery file " << backup_path_ << " removed";
117 void RecoveryFile::Detach() {
121 bool RecoveryFile::is_detached() const {
122 return path_.empty();
125 void RecoveryFile::set_unpacked_dir(
126 std::filesystem::path unpacked_dir) {
127 unpacked_dir_ = std::move(unpacked_dir);
130 void RecoveryFile::set_pkgid(std::string pkgid) {
131 pkgid_ = std::move(pkgid);
135 void RecoveryFile::set_backup_done(bool backup_done) {
136 backup_done_ = backup_done;
139 void RecoveryFile::set_cleanup(bool cleanup) {
143 void RecoveryFile::set_security_operation_done(bool security_operation_done) {
144 security_operation_done_ = security_operation_done;
147 const std::filesystem::path& RecoveryFile::unpacked_dir() const {
148 return unpacked_dir_;
151 const std::string& RecoveryFile::pkgid() const {
155 RequestType RecoveryFile::type() const {
159 bool RecoveryFile::backup_done() const {
163 bool RecoveryFile::cleanup() const {
167 bool RecoveryFile::security_operation_done() const {
168 return security_operation_done_;
171 bool RecoveryFile::ReadFileContent() {
172 FILE* handle = fopen(path_.c_str(), "r");
174 LOG(ERROR) << "Cannot read recovery file";
177 std::array<char, 200> data;
179 if (!fgets(data.data(), data.size(), handle)) {
180 type_ = RequestType::Unknown;
184 std::string mode(TruncateNewLine(data.data()));
185 auto iter = kStringToRequestMap.find(mode);
186 if (iter == kStringToRequestMap.end()) {
187 type_ = RequestType::Unknown;
189 type_ = iter->second;
192 if (!fgets(data.data(), data.size(), handle)) {
196 unpacked_dir_ = TruncateNewLine(data.data());
197 if (!fgets(data.data(), data.size(), handle)) {
201 pkgid_ = TruncateNewLine(data.data());
202 if (!fgets(data.data(), data.size(), handle)) {
206 std::string backup_flag = TruncateNewLine(data.data());
207 if (backup_flag == "true")
210 backup_done_ = false;
211 if (!fgets(data.data(), data.size(), handle)) {
215 std::string cleanup_flag = TruncateNewLine(data.data());
216 if (cleanup_flag == "cleanup")
220 if (!fgets(data.data(), data.size(), handle)) {
224 std::string security_operation_done_flag = TruncateNewLine(data.data());
225 if (security_operation_done_flag == "true")
226 security_operation_done_ = true;
228 security_operation_done_ = false;
233 bool RecoveryFile::WriteAndCommitFileContent() {
234 if (fs::exists(path_)) {
235 std::error_code error;
236 fs::rename(path_, backup_path_, error);
238 LOG(ERROR) << "Cannot backup recovery file:" << path_ <<
239 ", error: " << error;
244 std::ofstream ofs(path_);
246 LOG(ERROR) << "Cannot write recovery file";
251 case RequestType::Install:
252 ofs << kRecoveryInstallString << std::endl;
254 case RequestType::Update:
255 ofs << kRecoveryUpdateString << std::endl;
257 case RequestType::Uninstall:
258 ofs << kRecoveryUninstallationString << std::endl;
260 case RequestType::Reinstall:
261 ofs << kRecoveryRdsString << std::endl;
263 case RequestType::Delta:
264 ofs << kRecoveryDeltaString << std::endl;
266 case RequestType::MountInstall:
267 ofs << kRecoveryMountInstallString << std::endl;
269 case RequestType::MountUpdate:
270 ofs << kRecoveryMountUpdateString << std::endl;
272 case RequestType::ReadonlyUpdateInstall:
273 ofs << kRecoveryReadonlyUpdateInstallString << std::endl;
275 case RequestType::ReadonlyUpdateUninstall:
276 ofs << kRecoveryReadonlyUpdateUninstallString << std::endl;
279 ofs << kRecoveryUnknownString << std::endl;
282 ofs << unpacked_dir_.c_str() << std::endl;
283 ofs << pkgid_ << std::endl;
284 ofs << (backup_done_ ? "true" : "false") << std::endl;
285 ofs << (cleanup_ ? "cleanup" : "rollback") << std::endl;
286 ofs << (security_operation_done_ ? "true" : "false") << std::endl;
291 Remove(backup_path_);
295 } // namespace recovery
296 } // namespace common_installer