• 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 <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/hwfault_retry.h"
30 #include "updater/updater.h"
31 #include "updater/updater_const.h"
32 #include "updater_main.h"
33 #include "utils.h"
34 
35 namespace Updater {
36 using namespace Hpackage;
37 using namespace Updater::Utils;
38 
DeleteInstallTimeFile()39 void DeleteInstallTimeFile()
40 {
41     const std::string installTimeFilePath = std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE);
42     if (access(installTimeFilePath.c_str(), F_OK) != -1) {
43         (void)DeleteFile(installTimeFilePath);
44         LOG(INFO) << "delete install time file";
45     }
46 }
47 
IsDouble(const std::string & str)48 bool IsDouble(const std::string& str)
49 {
50     std::regex pattern("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$");
51     return std::regex_match(str, pattern);
52 }
53 
WriteInstallTime(UpdaterParams & upParams)54 void WriteInstallTime(UpdaterParams &upParams)
55 {
56     std::ofstream ofs;
57     ofs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::app | std::ios::out);
58     if (!ofs.is_open()) {
59         LOG(ERROR) << "open install time file fail";
60         return;
61     }
62     ofs << DurationToString(upParams.installTime, upParams.pkgLocation) << "\n";
63 }
64 
ReadInstallTime(UpdaterParams & upParams)65 void ReadInstallTime(UpdaterParams &upParams)
66 {
67     std::ifstream ifs;
68     std::string buf;
69     ifs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::in);
70     if (!ifs.is_open()) {
71         LOG(ERROR) << "read install time file fail";
72         return;
73     }
74     unsigned int index = 0;
75     while (getline(ifs, buf)) {
76         if (index >= upParams.pkgLocation) {
77             break;
78         }
79         if (IsDouble(buf)) {
80             double timeDistance = 0;
81             if (!Utils::ConvertToDouble(buf, timeDistance)) {
82                 LOG(ERROR) << "ConvertToDouble failed";
83                 return;
84             }
85             upParams.installTime[index++] = std::chrono::duration<double>(timeDistance);
86         } else {
87             LOG(ERROR) << "read install time is invalid";
88         }
89     }
90 }
91 
DeleteUpdaterPath(const std::string & path)92 bool DeleteUpdaterPath(const std::string &path)
93 {
94     auto pDir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(path.c_str()), closedir);
95     if (pDir == nullptr) {
96         LOG(INFO) << "Can not open dir";
97         return true;
98     }
99     bool sdcardTmp = false;
100     if (path.find("sdcard") != std::string::npos) {
101         sdcardTmp = true;
102     }
103     struct dirent *dp = nullptr;
104     while ((dp = readdir(pDir.get())) != nullptr) {
105         std::string currentName(dp->d_name);
106         if (currentName[0] == '.' || (currentName.compare("log") == 0) ||
107             (currentName.compare(UPDATER_RESULT_FILE) == 0) ||
108             (currentName.compare(UPDATER_LOCALE_FILE) == 0) ||
109             (currentName.compare(MODULE_UPDATE_RESULT_FILE) == 0) ||
110             (currentName.compare(UPLOAD_LOG_TIME_FILE) == 0) ||
111             (currentName.compare(INSTALL_TIME_FILE) == 0)) {
112             continue;
113         }
114         if (sdcardTmp && currentName.find(SDCARD_PACKAGE_SUFFIX) != std::string::npos) {
115             continue;
116         }
117         std::string tmpName(path);
118         tmpName.append("/" + currentName);
119         if (IsDirExist(tmpName)) {
120             DeleteUpdaterPath(tmpName);
121         }
122 #ifndef UPDATER_UT
123         remove(tmpName.c_str());
124 #endif
125     }
126     return true;
127 }
128 
ClearMisc()129 bool ClearMisc()
130 {
131     struct UpdateMessage cleanBoot {};
132     if (!WriteUpdaterMiscMsg(cleanBoot)) {
133         LOG(ERROR) << "ClearMisc clear boot message to misc failed";
134         return false;
135     }
136     auto miscBlockDev = GetBlockDeviceByMountPoint(MISC_PATH);
137     if (miscBlockDev.empty()) {
138         LOG(INFO) << "cannot get block device of partition";
139         miscBlockDev = MISC_FILE;
140     }
141     LOG(INFO) << "ClearMisc::misc path : " << miscBlockDev;
142     auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(miscBlockDev.c_str(), "rb+"), fclose);
143     if (fp == nullptr) {
144         LOG(ERROR) << "WriteVersionCode fopen failed" << " : " << strerror(errno);
145         return false;
146     }
147     if (fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET) != 0) {
148         LOG(ERROR) << "ClearMisc fseek failed";
149         return false;
150     }
151     off_t clearOffset = 0;
152     if (fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) != 1) {
153         LOG(ERROR) << "ClearMisc write misc initOffset 0 failed" << " : " << strerror(errno);
154         return false;
155     }
156 
157     struct PartitionRecordInfo cleanPartition {};
158     for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset +=
159         sizeof(PartitionRecordInfo)) {
160         if (fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET) != 0) {
161             LOG(ERROR) << "ClearMisc fseek failed";
162             return false;
163         }
164         if (fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) != 1) {
165             LOG(ERROR) << "ClearMisc write misc cleanPartition failed" << " : " << strerror(errno);
166             return false;
167         }
168     }
169     return true;
170 }
171 
IsSDCardExist(const std::string & sdcardPath)172 bool IsSDCardExist(const std::string &sdcardPath)
173 {
174     // Record system error codes.
175     int save_errno = errno;
176     struct stat st {};
177     if (stat(sdcardPath.c_str(), &st) < 0) {
178         return false;
179     } else {
180         errno = save_errno;
181         return true;
182     }
183 }
184 
IsMountDataAndSaveLogs(void)185 bool IsMountDataAndSaveLogs(void)
186 {
187     bool isSdCardMode = CheckUpdateMode(SDCARD_MODE);
188     bool isUsbMode = CheckUpdateMode(USB_MODE);
189     bool isSdCardIntralMode = CheckUpdateMode(SDCARD_INTRAL_MODE);
190     bool isLogMounted = GetMountStatusForMountPoint("/log") == MountStatus::MOUNT_MOUNTED;
191     bool isDataAlreadyMounted = GetMountStatusForMountPoint("/data") == MountStatus::MOUNT_MOUNTED;
192     return (!(isSdCardMode || isUsbMode) && (isDataAlreadyMounted || !isLogMounted)) || isSdCardIntralMode;
193 }
194 
DeleteUpdaterTmpFiles()195 static void DeleteUpdaterTmpFiles()
196 {
197     if (access(UPDATER_PATH, 0) == 0 && access(SDCARD_CARD_PATH, 0) != 0 && !DeleteUpdaterPath(UPDATER_PATH)) {
198         LOG(ERROR) << "DeleteUpdaterPath failed";
199     }
200     if (access(SDCARD_CARD_PATH, 0) == 0 && !DeleteUpdaterPath(SDCARD_CARD_PATH)) {
201         LOG(ERROR) << "Delete sdcard path failed";
202     }
203     if (access(Flashd::FLASHD_FILE_PATH, 0) == 0 && !DeleteUpdaterPath(Flashd::FLASHD_FILE_PATH)) {
204         LOG(ERROR) << "DeleteUpdaterPath failed";
205     }
206 }
207 
PostUpdater(bool clearMisc)208 void PostUpdater(bool clearMisc)
209 {
210     STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater";
211     bool isMountDataAndSaveLogs = IsMountDataAndSaveLogs();
212     (void)SetupPartitions(isMountDataAndSaveLogs);
213     UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_INIT_EVENT);
214     // clear update misc partition.
215     if (clearMisc && !ClearMisc()) {
216         LOG(ERROR) << "PostUpdater clear misc failed";
217     }
218     if (!access(COMMAND_FILE, 0) && unlink(COMMAND_FILE) != 0) {
219         LOG(ERROR) << "Delete command failed";
220     }
221     if (!HwFaultRetry::GetInstance().IsRetry()) {
222         DeleteUpdaterTmpFiles();
223     }
224     if (isMountDataAndSaveLogs) {
225         SaveLogs();
226     }
227 }
228 
InitMode(void) const229 void BootMode::InitMode(void) const
230 {
231     InitLogger(modeName);
232 #ifdef UPDATER_BUILD_VARIANT_USER
233     SetLogLevel(INFO);
234 #else
235     SetLogLevel(DEBUG);
236 #endif
237     LoadFstab();
238     STAGE(UPDATE_STAGE_OUT) << "Start " << modeName;
239     SetParameter(modePara.c_str(), "1");
240 }
241 
IsUpdater(const UpdateMessage & boot)242 bool IsUpdater(const UpdateMessage &boot)
243 {
244     return !IsFlashd(boot) && strncmp(boot.command, "boot_updater", sizeof("boot_updater") - 1) == 0;
245 }
246 
IsFlashd(const UpdateMessage & boot)247 bool IsFlashd(const UpdateMessage &boot)
248 {
249     return strncmp(boot.update, "boot_flash", sizeof("boot_flash") - 1) == 0;
250 }
251 
GetBootModes(void)252 std::vector<BootMode> &GetBootModes(void)
253 {
254     static std::vector<BootMode> bootModes {};
255     return bootModes;
256 }
257 
RegisterMode(const BootMode & mode)258 void RegisterMode(const BootMode &mode)
259 {
260     GetBootModes().push_back(mode);
261 }
262 
SelectMode(const UpdateMessage & boot)263 std::optional<BootMode> SelectMode(const UpdateMessage &boot)
264 {
265     const auto &modes = GetBootModes();
266 
267     // select modes by bootMode.cond which would check misc message
268     auto it = std::find_if(modes.begin(), modes.end(), [&boot] (const auto &bootMode) {
269         if (bootMode.cond != nullptr && bootMode.cond(boot)) {
270             LOG(INFO) << "condition for mode " << bootMode.modeName << " is satisfied";
271             return true;
272         }
273         LOG(WARNING) << "condition for mode " << bootMode.modeName << " is not satisfied";
274         return false;
275     });
276     // misc check failed for each mode, then enter updater mode
277     if (it == modes.end() || it->entryFunc == nullptr) {
278         LOG(WARNING) << "find valid mode failed, enter updater Mode";
279         return std::nullopt;
280     }
281 
282     LOG(INFO) << "enter " << it->modeName << " mode";
283     return *it;
284 }
285 } // namespace Updater
286