Adjusted setters
[platform/core/appfw/app-installers.git] / src / common / recovery_file.cc
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.
4
5 #include "common/recovery_file.h"
6
7 #include <boost/filesystem/operations.hpp>
8 #include <boost/system/error_code.hpp>
9
10 #include <manifest_parser/utils/logging.h>
11
12 #include <array>
13 #include <cstring>
14 #include <map>
15 #include <utility>
16
17 #include "common/installer_context.h"
18
19 namespace bf = boost::filesystem;
20 namespace bs = boost::system;
21 namespace ci = common_installer;
22
23 namespace {
24
25 const char kRecoveryNewInstallationString[] = "NEW";
26 const char kRecoveryUpdateInstallationString[] = "UPDATE";
27 const char kRecoveryUninstallationString[] = "UNINSTALLATION";
28 const char kRecoveryRdsString[] = "RDS";
29 const char kRecoveryDeltaString[] = "DELTA";
30 const char kRecoveryUnknownString[] = "UNKNOWN";
31
32 const std::map<std::string, ci::RequestType> kStringToRequestMap = {
33   {kRecoveryNewInstallationString, ci::RequestType::Install},
34   {kRecoveryUpdateInstallationString, ci::RequestType::Update},
35   {kRecoveryUninstallationString, ci::RequestType::Uninstall},
36   {kRecoveryRdsString, ci::RequestType::Reinstall},
37   {kRecoveryDeltaString, ci::RequestType::Delta}
38 };
39
40 std::string TruncateNewLine(const char* data) {
41   int length = strlen(data);
42   if (data[length - 1] == '\n')
43       --length;
44   return std::string(data, length);
45 }
46
47 }  // namespace
48
49 namespace common_installer {
50 namespace recovery {
51
52 std::unique_ptr<RecoveryFile> RecoveryFile::CreateRecoveryFileForPath(
53     const boost::filesystem::path& path) {
54   if (bf::exists(path)) {
55     LOG(ERROR) << "Recovery file already exists!";
56     return nullptr;
57   }
58   std::unique_ptr<RecoveryFile> file(new RecoveryFile(path, false));
59   if (file->is_detached()) {
60     LOG(ERROR) << "Failed to access file";
61     return nullptr;
62   }
63   return file;
64 }
65
66 std::unique_ptr<RecoveryFile> RecoveryFile::OpenRecoveryFileForPath(
67     const boost::filesystem::path& path) {
68   if (!bf::exists(path)) {
69     LOG(ERROR) << "Cannot open recovery file";
70     return nullptr;
71   }
72   std::unique_ptr<RecoveryFile> file(new RecoveryFile(path, true));
73   if (file->is_detached()) {
74     LOG(ERROR) << "Failed to read recovery file";
75     return nullptr;
76   }
77   return file;
78 }
79
80 RecoveryFile::RecoveryFile(const bf::path& path, bool load)
81     : path_(path) {
82   if (load) {
83     if (!ReadFileContent()) {
84       path_.clear();
85       return;
86     }
87   } else {
88     // create file
89     FILE* handle = fopen(path.c_str(), "w");
90     if (!handle) {
91       path_.clear();
92       return;
93     }
94     fclose(handle);
95     LOG(DEBUG) << "Recovery file " << path_ << " created";
96   }
97 }
98
99 RecoveryFile::~RecoveryFile() {
100   if (!path_.empty()) {
101     bs::error_code error;
102     bf::remove(path_, error);
103     LOG(DEBUG) << "Recovery file " << path_ << " removed";
104   }
105 }
106
107 void RecoveryFile::Detach() {
108   path_.clear();
109 }
110
111 bool RecoveryFile::is_detached() const {
112   return path_.empty();
113 }
114
115 void RecoveryFile::set_unpacked_dir(
116     boost::filesystem::path unpacked_dir) {
117   unpacked_dir_ = std::move(unpacked_dir);
118 }
119
120 void RecoveryFile::set_pkgid(std::string pkgid) {
121   pkgid_ = std::move(pkgid);
122 }
123
124 void RecoveryFile::set_type(RequestType type) {
125   type_ = type;
126 }
127
128 const boost::filesystem::path& RecoveryFile::unpacked_dir() const {
129   return unpacked_dir_;
130 }
131
132 const std::string& RecoveryFile::pkgid() const {
133   return pkgid_;
134 }
135
136 RequestType RecoveryFile::type() const {
137   return type_;
138 }
139
140 bool RecoveryFile::ReadFileContent() {
141   FILE* handle = fopen(path_.c_str(), "r");
142   if (!handle) {
143     LOG(ERROR) << "Cannot read recovery file";
144     return false;
145   }
146   std::array<char, 200> data;
147   data[0] = '\0';
148   if (!fgets(data.data(), data.size(), handle)) {
149     type_ = RequestType::Unknown;
150     fclose(handle);
151     return true;
152   }
153   std::string mode(TruncateNewLine(data.data()));
154   auto iter = kStringToRequestMap.find(mode);
155   if (iter == kStringToRequestMap.end()) {
156     type_ = RequestType::Unknown;
157   } else {
158     type_ = iter->second;
159   }
160
161   if (!fgets(data.data(), data.size(), handle)) {
162     fclose(handle);
163     return true;
164   }
165   unpacked_dir_ = TruncateNewLine(data.data());
166   if (!fgets(data.data(), data.size(), handle)) {
167     fclose(handle);
168     return true;
169   }
170   pkgid_ = TruncateNewLine(data.data());
171   fclose(handle);
172   return true;
173 }
174
175 bool RecoveryFile::WriteAndCommitFileContent() {
176   FILE* handle = fopen(path_.c_str(), "w");
177   if (!handle) {
178     LOG(ERROR) << "Cannot write recovery file";
179     return false;
180   }
181   switch (type_) {
182   case RequestType::Install:
183     fputs(kRecoveryNewInstallationString, handle);
184     break;
185   case RequestType::Update:
186     fputs(kRecoveryUpdateInstallationString, handle);
187     break;
188   case RequestType::Uninstall:
189     fputs(kRecoveryUninstallationString, handle);
190     break;
191   case RequestType::Reinstall:
192     fputs(kRecoveryRdsString, handle);
193     break;
194   case RequestType::Delta:
195     fputs(kRecoveryDeltaString, handle);
196     break;
197   default:
198     fputs(kRecoveryUnknownString, handle);
199     break;
200   }
201   fputs("\n", handle);
202   fputs(unpacked_dir_.c_str(), handle);
203   fputs("\n", handle);
204   fputs(pkgid_.c_str(), handle);
205   fputs("\n", handle);
206   fclose(handle);
207   return true;
208 }
209
210 }  // namespace recovery
211 }  // namespace common_installer
212