1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <chrono>
16 #include <dirent.h>
17 #include <fcntl.h>
18 #include <sys/mount.h>
19 #include <sys/stat.h>
20 #include <sys/statvfs.h>
21 #include <regex>
22
23 #include "applypatch/partition_record.h"
24 #include "flashd/flashd.h"
25 #include "log/log.h"
26 #include "misc_info/misc_info.h"
27 #include "package/pkg_manager.h"
28 #include "securec.h"
29 #include "updater/updater.h"
30 #include "updater/updater_const.h"
31 #include "updater_main.h"
32 #include "utils.h"
33
34 namespace Updater {
35 using namespace Hpackage;
36 using namespace Updater::Utils;
37
DeleteInstallTimeFile()38 void DeleteInstallTimeFile()
39 {
40 const std::string installTimeFilePath = std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE);
41 if (access(installTimeFilePath.c_str(), F_OK) != -1) {
42 (void)DeleteFile(installTimeFilePath);
43 LOG(INFO) << "delete install time file";
44 }
45 }
46
IsDouble(const std::string& str)47 bool IsDouble(const std::string& str)
48 {
49 std::regex pattern("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$");
50 return std::regex_match(str, pattern);
51 }
52
WriteInstallTime(UpdaterParams &upParams)53 void WriteInstallTime(UpdaterParams &upParams)
54 {
55 std::ofstream ofs;
56 ofs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::app | std::ios::out);
57 if (!ofs.is_open()) {
58 LOG(ERROR) << "open install time file fail";
59 return;
60 }
61 ofs << DurationToString(upParams.installTime, upParams.pkgLocation) << "\n";
62 }
63
ReadInstallTime(UpdaterParams &upParams)64 void ReadInstallTime(UpdaterParams &upParams)
65 {
66 std::ifstream ifs;
67 std::string buf;
68 ifs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::in);
69 if (!ifs.is_open()) {
70 LOG(ERROR) << "read install time file fail";
71 return;
72 }
73 unsigned int index = 0;
74 while (getline(ifs, buf)) {
75 if (index >= upParams.pkgLocation) {
76 break;
77 }
78 if (IsDouble(buf)) {
79 upParams.installTime[index++] = std::chrono::duration<double>(std::stod(buf));
80 } else {
81 LOG(ERROR) << "read install time is invalid";
82 }
83 }
84 }
85
DeleteUpdaterPath(const std::string &path)86 bool DeleteUpdaterPath(const std::string &path)
87 {
88 auto pDir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(path.c_str()), closedir);
89 if (pDir == nullptr) {
90 LOG(INFO) << "Can not open dir";
91 return true;
92 }
93 bool sdcardTmp = false;
94 if (path.find("sdcard") != std::string::npos) {
95 sdcardTmp = true;
96 }
97 struct dirent *dp = nullptr;
98 while ((dp = readdir(pDir.get())) != nullptr) {
99 std::string currentName(dp->d_name);
100 if (currentName[0] == '.' || (currentName.compare("log") == 0) ||
101 (currentName.compare(UPDATER_RESULT_FILE) == 0) ||
102 (currentName.compare(UPDATER_LOCALE_FILE) == 0) ||
103 (currentName.compare(MODULE_UPDATE_RESULT_FILE) == 0) ||
104 (currentName.compare(UPLOAD_LOG_TIME_FILE) == 0)) {
105 continue;
106 }
107 if (sdcardTmp && currentName.find(SDCARD_PACKAGE_SUFFIX) != std::string::npos) {
108 continue;
109 }
110 std::string tmpName(path);
111 tmpName.append("/" + currentName);
112 if (IsDirExist(tmpName)) {
113 DeleteUpdaterPath(tmpName);
114 }
115 #ifndef UPDATER_UT
116 remove(tmpName.c_str());
117 #endif
118 }
119 return true;
120 }
121
ClearMisc()122 bool ClearMisc()
123 {
124 struct UpdateMessage cleanBoot {};
125 if (!WriteUpdaterMiscMsg(cleanBoot)) {
126 LOG(ERROR) << "ClearMisc clear boot message to misc failed";
127 return false;
128 }
129 auto miscBlockDev = GetBlockDeviceByMountPoint(MISC_PATH);
130 if (miscBlockDev.empty()) {
131 LOG(INFO) << "cannot get block device of partition";
132 miscBlockDev = MISC_FILE;
133 }
134 LOG(INFO) << "ClearMisc::misc path : " << miscBlockDev;
135 auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(miscBlockDev.c_str(), "rb+"), fclose);
136 if (fp == nullptr) {
137 LOG(ERROR) << "WriteVersionCode fopen failed" << " : " << strerror(errno);
138 return false;
139 }
140 if (fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET) != 0) {
141 LOG(ERROR) << "ClearMisc fseek failed";
142 return false;
143 }
144 off_t clearOffset = 0;
145 if (fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) != 1) {
146 LOG(ERROR) << "ClearMisc write misc initOffset 0 failed" << " : " << strerror(errno);
147 return false;
148 }
149
150 struct PartitionRecordInfo cleanPartition {};
151 for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset +=
152 sizeof(PartitionRecordInfo)) {
153 if (fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET) != 0) {
154 LOG(ERROR) << "ClearMisc fseek failed";
155 return false;
156 }
157 if (fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) != 1) {
158 LOG(ERROR) << "ClearMisc write misc cleanPartition failed" << " : " << strerror(errno);
159 return false;
160 }
161 }
162 return true;
163 }
164
IsSDCardExist(const std::string &sdcardPath)165 bool IsSDCardExist(const std::string &sdcardPath)
166 {
167 // Record system error codes.
168 int save_errno = errno;
169 struct stat st {};
170 if (stat(sdcardPath.c_str(), &st) < 0) {
171 return false;
172 } else {
173 errno = save_errno;
174 return true;
175 }
176 }
177
PostUpdater(bool clearMisc)178 void PostUpdater(bool clearMisc)
179 {
180 STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater";
181
182 if (!CheckUpdateMode(SDCARD_MODE) && !CheckUpdateMode(USB_MODE) && (CheckUpdateMode(OTA_MODE) ||
183 GetMountStatusForMountPoint("/log") != MountStatus::MOUNT_MOUNTED)) {
184 (void)SetupPartitions();
185 } else {
186 (void)SetupPartitions(false);
187 }
188 UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_INIT_EVENT);
189 // clear update misc partition.
190 if (clearMisc && !ClearMisc()) {
191 LOG(ERROR) << "PostUpdater clear misc failed";
192 }
193 if (!access(COMMAND_FILE, 0) && unlink(COMMAND_FILE) != 0) {
194 LOG(ERROR) << "Delete command failed";
195 }
196
197 // delete updater tmp files
198 if (access(UPDATER_PATH, 0) == 0 && access(SDCARD_CARD_PATH, 0) != 0 && !DeleteUpdaterPath(UPDATER_PATH)) {
199 LOG(ERROR) << "DeleteUpdaterPath failed";
200 }
201 if (access(SDCARD_CARD_PATH, 0) == 0 && !DeleteUpdaterPath(SDCARD_CARD_PATH)) {
202 LOG(ERROR) << "Delete sdcard path failed";
203 }
204 if (access(Flashd::FLASHD_FILE_PATH, 0) == 0 && !DeleteUpdaterPath(Flashd::FLASHD_FILE_PATH)) {
205 LOG(ERROR) << "DeleteUpdaterPath failed";
206 }
207 if (!CheckUpdateMode(SDCARD_MODE) && !CheckUpdateMode(USB_MODE) &&
208 GetMountStatusForMountPoint("/log") != MountStatus::MOUNT_MOUNTED) {
209 SaveLogs();
210 }
211 }
212
InitMode(void) const213 void BootMode::InitMode(void) const
214 {
215 InitLogger(modeName);
216 #ifdef UPDATER_BUILD_VARIANT_USER
217 SetLogLevel(INFO);
218 #else
219 SetLogLevel(DEBUG);
220 #endif
221 LoadFstab();
222 STAGE(UPDATE_STAGE_OUT) << "Start " << modeName;
223 SetParameter(modePara.c_str(), "1");
224 }
225
IsUpdater(const UpdateMessage &boot)226 bool IsUpdater(const UpdateMessage &boot)
227 {
228 return !IsFlashd(boot) && strncmp(boot.command, "boot_updater", sizeof("boot_updater") - 1) == 0;
229 }
230
IsFlashd(const UpdateMessage &boot)231 bool IsFlashd(const UpdateMessage &boot)
232 {
233 return strncmp(boot.update, "boot_flash", sizeof("boot_flash") - 1) == 0;
234 }
235
GetBootModes(void)236 std::vector<BootMode> &GetBootModes(void)
237 {
238 static std::vector<BootMode> bootModes {};
239 return bootModes;
240 }
241
RegisterMode(const BootMode &mode)242 void RegisterMode(const BootMode &mode)
243 {
244 GetBootModes().push_back(mode);
245 }
246
SelectMode(const UpdateMessage &boot)247 std::optional<BootMode> SelectMode(const UpdateMessage &boot)
248 {
249 const auto &modes = GetBootModes();
250
251 // select modes by bootMode.cond which would check misc message
252 auto it = std::find_if(modes.begin(), modes.end(), [&boot] (const auto &bootMode) {
253 if (bootMode.cond != nullptr && bootMode.cond(boot)) {
254 LOG(INFO) << "condition for mode " << bootMode.modeName << " is satisfied";
255 return true;
256 }
257 LOG(WARNING) << "condition for mode " << bootMode.modeName << " is not satisfied";
258 return false;
259 });
260 // misc check failed for each mode, then enter updater mode
261 if (it == modes.end() || it->entryFunc == nullptr) {
262 LOG(WARNING) << "find valid mode failed, enter updater Mode";
263 return std::nullopt;
264 }
265
266 LOG(INFO) << "enter " << it->modeName << " mode";
267 return *it;
268 }
269 } // namespace Updater
270