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 <boost/filesystem/operations.hpp>
8 #include <boost/system/error_code.hpp>
10 #include <manifest_parser/utils/logging.h>
17 #include "common/installer_context.h"
18 #include "common/utils/file_util.h"
20 namespace bf = boost::filesystem;
21 namespace bs = boost::system;
22 namespace ci = common_installer;
26 const char kRecoveryInstallString[] = "NEW";
27 const char kRecoveryUpdateString[] = "UPDATE";
28 const char kRecoveryUninstallationString[] = "UNINSTALL";
29 const char kRecoveryRdsString[] = "RDS";
30 const char kRecoveryDeltaString[] = "DELTA";
31 const char kRecoveryMountInstallString[] = "MOUNTINSTALL";
32 const char kRecoveryMountUpdateString[] = "MOUNTUPDATE";
33 const char kRecoveryReadonlyUpdateInstallString[] = "READONLYUPDATEINSTALL";
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},
48 std::string TruncateNewLine(const char* data) {
49 int length = strlen(data);
50 if (data[length - 1] == '\n')
52 return std::string(data, length);
57 namespace common_installer {
60 std::unique_ptr<RecoveryFile> RecoveryFile::CreateRecoveryFile(
61 const boost::filesystem::path& path, RequestType type) {
62 if (bf::exists(path)) {
63 LOG(ERROR) << "Recovery file already exists!";
66 std::unique_ptr<RecoveryFile> file(new RecoveryFile(path, type, false));
67 if (file->is_detached()) {
68 LOG(ERROR) << "Failed to access file";
74 std::unique_ptr<RecoveryFile> RecoveryFile::OpenRecoveryFile(
75 const boost::filesystem::path& path) {
76 if (!bf::exists(path)) {
77 LOG(ERROR) << "Cannot open recovery file";
80 std::unique_ptr<RecoveryFile> file(new RecoveryFile(path,
81 RequestType::Unknown, true));
82 if (file->is_detached()) {
83 LOG(ERROR) << "Failed to read recovery file";
89 RecoveryFile::RecoveryFile(const bf::path& path, RequestType type, bool load)
90 : type_(type), path_(path), backup_done_(false) {
92 if (!ReadFileContent()) {
98 if (!WriteAndCommitFileContent()) {
102 LOG(DEBUG) << "Recovery file " << path_ << " created";
106 RecoveryFile::~RecoveryFile() {
108 LOG(DEBUG) << "Recovery file " << path_ << " removed";
111 void RecoveryFile::Detach() {
115 bool RecoveryFile::is_detached() const {
116 return path_.empty();
119 void RecoveryFile::set_unpacked_dir(
120 boost::filesystem::path unpacked_dir) {
121 unpacked_dir_ = std::move(unpacked_dir);
124 void RecoveryFile::set_pkgid(std::string pkgid) {
125 pkgid_ = std::move(pkgid);
129 void RecoveryFile::set_backup_done(bool backup_done) {
130 backup_done_ = backup_done;
133 const boost::filesystem::path& RecoveryFile::unpacked_dir() const {
134 return unpacked_dir_;
137 const std::string& RecoveryFile::pkgid() const {
141 RequestType RecoveryFile::type() const {
145 bool RecoveryFile::backup_done() const {
149 bool RecoveryFile::ReadFileContent() {
150 FILE* handle = fopen(path_.c_str(), "r");
152 LOG(ERROR) << "Cannot read recovery file";
155 std::array<char, 200> data;
157 if (!fgets(data.data(), data.size(), handle)) {
158 type_ = RequestType::Unknown;
162 std::string mode(TruncateNewLine(data.data()));
163 auto iter = kStringToRequestMap.find(mode);
164 if (iter == kStringToRequestMap.end()) {
165 type_ = RequestType::Unknown;
167 type_ = iter->second;
170 if (!fgets(data.data(), data.size(), handle)) {
174 unpacked_dir_ = TruncateNewLine(data.data());
175 if (!fgets(data.data(), data.size(), handle)) {
179 pkgid_ = TruncateNewLine(data.data());
180 if (!fgets(data.data(), data.size(), handle)) {
184 std::string backup_flag = TruncateNewLine(data.data());
185 if (backup_flag == "true")
188 backup_done_ = false;
193 bool RecoveryFile::WriteAndCommitFileContent() {
195 FILE* handle = fopen(path_.c_str(), "wx");
197 LOG(ERROR) << "Cannot write recovery file";
201 case RequestType::Install:
202 fputs(kRecoveryInstallString, handle);
204 case RequestType::Update:
205 fputs(kRecoveryUpdateString, handle);
207 case RequestType::Uninstall:
208 fputs(kRecoveryUninstallationString, handle);
210 case RequestType::Reinstall:
211 fputs(kRecoveryRdsString, handle);
213 case RequestType::Delta:
214 fputs(kRecoveryDeltaString, handle);
216 case RequestType::MountInstall:
217 fputs(kRecoveryMountInstallString, handle);
219 case RequestType::MountUpdate:
220 fputs(kRecoveryMountUpdateString, handle);
222 case RequestType::ReadonlyUpdateInstall:
223 fputs(kRecoveryReadonlyUpdateInstallString, handle);
226 fputs(kRecoveryUnknownString, handle);
230 fputs(unpacked_dir_.c_str(), handle);
232 fputs(pkgid_.c_str(), handle);
234 fputs(backup_done_ ? "true" : "false", handle);
241 } // namespace recovery
242 } // namespace common_installer