• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <regex>
17 #include <thread>
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <sched.h>
21 #include <sys/mount.h>
22 #include <sys/stat.h>
23 #include <sys/statvfs.h>
24 #include <sys/syscall.h>
25 
26 #include "applypatch/partition_record.h"
27 #include "flashd/flashd.h"
28 #include "log/log.h"
29 #include "misc_info/misc_info.h"
30 #include "package/pkg_manager.h"
31 #include "securec.h"
32 #include "updater/hardware_fault_retry.h"
33 #include "updater/updater.h"
34 #include "updater/updater_const.h"
35 #include "updater_main.h"
36 #include "utils.h"
37 
38 namespace Updater {
39 using namespace Hpackage;
40 using namespace Updater::Utils;
41 
DeleteInstallTimeFile()42 void DeleteInstallTimeFile()
43 {
44     const std::string installTimeFilePath = std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE);
45     if (access(installTimeFilePath.c_str(), F_OK) != -1) {
46         (void)DeleteFile(installTimeFilePath);
47         LOG(INFO) << "delete install time file";
48     }
49 }
50 
IsDouble(const std::string & str)51 bool IsDouble(const std::string& str)
52 {
53     std::regex pattern("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$");
54     if (!std::regex_match(str, pattern)) {
55         LOG(ERROR) << "match double failed";
56         return false;
57     }
58     return true;
59 }
60 
WriteInstallTime(UpdaterParams & upParams)61 void WriteInstallTime(UpdaterParams &upParams)
62 {
63     std::ofstream ofs;
64     ofs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::app | std::ios::out);
65     if (!ofs.is_open()) {
66         LOG(ERROR) << "open install time file fail";
67         return;
68     }
69     ofs << DurationToString(upParams.installTime, upParams.pkgLocation) << "\n";
70 }
71 
ReadInstallTime(UpdaterParams & upParams)72 void ReadInstallTime(UpdaterParams &upParams)
73 {
74     std::ifstream ifs;
75     std::string buf;
76     ifs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::in);
77     if (!ifs.is_open()) {
78         LOG(ERROR) << "read install time file fail";
79         return;
80     }
81     unsigned int index = 0;
82     while (getline(ifs, buf)) {
83         if (index >= upParams.pkgLocation) {
84             break;
85         }
86         if (IsDouble(buf)) {
87             double timeDistance = 0;
88             if (!Utils::ConvertToDouble(buf, timeDistance)) {
89                 LOG(ERROR) << "ConvertToDouble failed";
90                 return;
91             }
92             upParams.installTime[index++] = std::chrono::duration<double>(timeDistance);
93         } else {
94             LOG(ERROR) << "read install time is invalid";
95         }
96     }
97 }
98 
DeleteUpdaterPath(const std::string & path)99 bool DeleteUpdaterPath(const std::string &path)
100 {
101     auto pDir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(path.c_str()), closedir);
102     if (pDir == nullptr) {
103         LOG(INFO) << "Can not open dir";
104         return true;
105     }
106     bool sdcardTmp = false;
107     if (path.find("sdcard") != std::string::npos) {
108         sdcardTmp = true;
109     }
110     struct dirent *dp = nullptr;
111     while ((dp = readdir(pDir.get())) != nullptr) {
112         std::string currentName(dp->d_name);
113         if (currentName[0] == '.' || (currentName.compare("log") == 0) ||
114             (currentName.compare(UPDATER_RESULT_FILE) == 0) ||
115             (currentName.compare(UPDATER_LOCALE_FILE) == 0) ||
116             (currentName.compare(MODULE_UPDATE_RESULT_FILE) == 0) ||
117             (currentName.compare(UPLOAD_LOG_TIME_FILE) == 0) ||
118             (currentName.compare(INSTALL_TIME_FILE) == 0) ||
119             (currentName.compare(ROLLBACK_FILE) == 0)) {
120             continue;
121         }
122         if (sdcardTmp && currentName.find(SDCARD_PACKAGE_SUFFIX) != std::string::npos) {
123             continue;
124         }
125         std::string tmpName(path);
126         tmpName.append("/" + currentName);
127         if (IsDirExist(tmpName)) {
128             DeleteUpdaterPath(tmpName);
129         }
130 #ifndef UPDATER_UT
131         remove(tmpName.c_str());
132 #endif
133     }
134     return true;
135 }
136 
ClearMisc()137 bool ClearMisc()
138 {
139     struct UpdateMessage cleanBoot {};
140     if (!WriteUpdaterMiscMsg(cleanBoot)) {
141         LOG(ERROR) << "ClearMisc clear boot message to misc failed";
142         return false;
143     }
144     auto miscBlockDev = GetBlockDeviceByMountPoint(MISC_PATH);
145     if (miscBlockDev.empty()) {
146         LOG(INFO) << "cannot get block device of partition";
147         miscBlockDev = MISC_FILE;
148     }
149     LOG(INFO) << "ClearMisc::misc path : " << miscBlockDev;
150     auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(miscBlockDev.c_str(), "rb+"), fclose);
151     if (fp == nullptr) {
152         LOG(ERROR) << "WriteVersionCode fopen failed" << " : " << strerror(errno);
153         return false;
154     }
155     if (fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET) != 0) {
156         LOG(ERROR) << "ClearMisc fseek failed";
157         return false;
158     }
159     off_t clearOffset = 0;
160     if (fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) != 1) {
161         LOG(ERROR) << "ClearMisc write misc initOffset 0 failed" << " : " << strerror(errno);
162         return false;
163     }
164 
165     struct PartitionRecordInfo cleanPartition {};
166     for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset +=
167         sizeof(PartitionRecordInfo)) {
168         if (fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET) != 0) {
169             LOG(ERROR) << "ClearMisc fseek failed";
170             return false;
171         }
172         if (fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) != 1) {
173             LOG(ERROR) << "ClearMisc write misc cleanPartition failed" << " : " << strerror(errno);
174             return false;
175         }
176     }
177     return true;
178 }
179 
IsSDCardExist(const std::string & sdcardPath)180 bool IsSDCardExist(const std::string &sdcardPath)
181 {
182     // Record system error codes.
183     int save_errno = errno;
184     struct stat st {};
185     if (stat(sdcardPath.c_str(), &st) < 0) {
186         return false;
187     } else {
188         errno = save_errno;
189         return true;
190     }
191 }
192 
IsMountDataAndSaveLogs(void)193 bool IsMountDataAndSaveLogs(void)
194 {
195     bool isSdCardMode = CheckUpdateMode(SDCARD_MODE);
196     bool isUsbMode = CheckUpdateMode(USB_MODE);
197     bool isSdCardIntralMode = CheckUpdateMode(SDCARD_INTRAL_MODE);
198     bool isLogMounted = GetMountStatusForMountPoint("/log") == MountStatus::MOUNT_MOUNTED;
199     bool isDataAlreadyMounted = GetMountStatusForMountPoint("/data") == MountStatus::MOUNT_MOUNTED;
200     return (!(isSdCardMode || isUsbMode) && (isDataAlreadyMounted || !isLogMounted)) || isSdCardIntralMode;
201 }
202 
DeleteUpdaterTmpFiles()203 static void DeleteUpdaterTmpFiles()
204 {
205     if (access(UPDATER_PATH, 0) == 0 && access(SDCARD_CARD_PATH, 0) != 0 && !DeleteUpdaterPath(UPDATER_PATH)) {
206         LOG(ERROR) << "DeleteUpdaterPath failed";
207     }
208     if (access(SDCARD_CARD_PATH, 0) == 0 && !DeleteUpdaterPath(SDCARD_CARD_PATH)) {
209         LOG(ERROR) << "Delete sdcard path failed";
210     }
211     if (access(Flashd::FLASHD_FILE_PATH, 0) == 0 && !DeleteUpdaterPath(Flashd::FLASHD_FILE_PATH)) {
212         LOG(ERROR) << "DeleteUpdaterPath failed";
213     }
214 }
215 
PostUpdater(bool clearMisc)216 void PostUpdater(bool clearMisc)
217 {
218     STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater";
219     bool isMountDataAndSaveLogs = IsMountDataAndSaveLogs();
220     (void)SetupPartitions(isMountDataAndSaveLogs);
221     UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_INIT_EVENT);
222     // clear update misc partition.
223     if (clearMisc && !ClearMisc()) {
224         LOG(ERROR) << "PostUpdater clear misc failed";
225     }
226     if (!access(COMMAND_FILE, 0) && unlink(COMMAND_FILE) != 0) {
227         LOG(ERROR) << "Delete command failed";
228     }
229     if (!HardwareFaultRetry::GetInstance().IsRetry()) {
230         DeleteUpdaterTmpFiles();
231     }
232     if (isMountDataAndSaveLogs) {
233         SaveLogs();
234     }
235 }
236 
InitMode(void) const237 void BootMode::InitMode(void) const
238 {
239     InitLogger(modeName);
240 #ifdef UPDATER_BUILD_VARIANT_USER
241     SetLogLevel(INFO);
242 #else
243     SetLogLevel(DEBUG);
244 #endif
245     LoadFstab();
246     STAGE(UPDATE_STAGE_OUT) << "Start " << modeName;
247     SetParameter(modePara.c_str(), "1");
248 }
249 
IsUpdater(const UpdateMessage & boot)250 bool IsUpdater(const UpdateMessage &boot)
251 {
252     return !IsFlashd(boot) && strncmp(boot.command, "boot_updater", sizeof("boot_updater") - 1) == 0;
253 }
254 
IsFlashd(const UpdateMessage & boot)255 bool IsFlashd(const UpdateMessage &boot)
256 {
257     return strncmp(boot.update, "boot_flash", sizeof("boot_flash") - 1) == 0;
258 }
259 
GetBootModes(void)260 std::vector<BootMode> &GetBootModes(void)
261 {
262     static std::vector<BootMode> bootModes {};
263     return bootModes;
264 }
265 
RegisterMode(const BootMode & mode)266 void RegisterMode(const BootMode &mode)
267 {
268     GetBootModes().push_back(mode);
269 }
270 
SelectMode(const UpdateMessage & boot)271 std::optional<BootMode> SelectMode(const UpdateMessage &boot)
272 {
273     const auto &modes = GetBootModes();
274 
275     // select modes by bootMode.cond which would check misc message
276     auto it = std::find_if(modes.begin(), modes.end(), [&boot] (const auto &bootMode) {
277         if (bootMode.cond != nullptr && bootMode.cond(boot)) {
278             LOG(INFO) << "condition for mode " << bootMode.modeName << " is satisfied";
279             return true;
280         }
281         LOG(WARNING) << "condition for mode " << bootMode.modeName << " is not satisfied";
282         return false;
283     });
284     // misc check failed for each mode, then enter updater mode
285     if (it == modes.end() || it->entryFunc == nullptr) {
286         LOG(WARNING) << "find valid mode failed, enter updater Mode";
287         return std::nullopt;
288     }
289 
290     LOG(INFO) << "enter " << it->modeName << " mode";
291     return *it;
292 }
293 
SetCpuAffinityByPid(const UpdaterParams & upParams,unsigned int reservedCores)294 bool SetCpuAffinityByPid(const UpdaterParams &upParams, unsigned int reservedCores)
295 {
296     static std::mutex setAffinityLock;
297     std::lock_guard<std::mutex> lock(setAffinityLock);
298     std::vector<std::string> binaryTids = upParams.binaryTids;
299     if (upParams.binaryPid == -1 || std::find(
300         binaryTids.begin(), binaryTids.end(), std::to_string(upParams.binaryPid)) == binaryTids.end()) {
301         LOG(WARNING) << "invalid binaryPid:" << upParams.binaryPid;
302         return false;
303     }
304     unsigned int coreCount = std::thread::hardware_concurrency();
305     LOG(INFO) << "coreCount:" << coreCount << ", reservedCores:" << reservedCores;
306     if (coreCount <= reservedCores) {
307         LOG(WARNING) << "coreCount:" << coreCount << " <= " << reservedCores;
308         return false;
309     }
310     cpu_set_t mask;
311     CPU_ZERO(&mask);
312     for (unsigned int i = 0; i < coreCount - reservedCores; i++) {
313         CPU_SET(i, &mask);
314     }
315     int syscallRes;
316     for (auto &str : binaryTids) {
317         int32_t temp = -1;
318         if (!Utils::ConvertToLong(str, temp)) {
319             LOG(ERROR) << "ConvertToLong failed:" << str;
320             continue;
321         }
322         pid_t tid = static_cast<pid_t>(temp);
323         syscallRes = syscall(__NR_sched_setaffinity, tid, sizeof(mask), &mask);
324         LOG(INFO) << "setaffinity tid:" << tid;
325         if (syscallRes != 0) {
326             LOG(ERROR) << "set affinity faild:" << syscallRes;
327         }
328     }
329     return true;
330 }
331 
UpdateBinaryTids(const std::vector<std::string> & output,UpdaterParams & upParams)332 void UpdateBinaryTids(const std::vector<std::string> &output, UpdaterParams &upParams)
333 {
334     if (output.size() < DEFAULT_PROCESS_NUM) {
335         LOG(ERROR) << "check output fail";
336         return;
337     }
338     auto outputInfo = Trim(output[1]);
339     LOG(INFO) << "binary tids:" << outputInfo;
340     upParams.binaryTids = SplitString(outputInfo, ",");
341     if (upParams.isLoadReduction) {
342         unsigned int coreCount = std::thread::hardware_concurrency();
343         unsigned int reservedCores = coreCount - LITTLE_CPU_CORES;
344         SetCpuAffinityByPid(upParams, reservedCores);
345     }
346 }
347 } // namespace Updater
348