• 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/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             continue;
105         }
106         if (sdcardTmp && currentName.find(SDCARD_PACKAGE_SUFFIX) != std::string::npos) {
107             continue;
108         }
109         std::string tmpName(path);
110         tmpName.append("/" + currentName);
111         if (IsDirExist(tmpName)) {
112             DeleteUpdaterPath(tmpName);
113         }
114 #ifndef UPDATER_UT
115         remove(tmpName.c_str());
116 #endif
117     }
118     return true;
119 }
120 
ClearMisc()121 bool ClearMisc()
122 {
123     struct UpdateMessage cleanBoot {};
124     if (!WriteUpdaterMiscMsg(cleanBoot)) {
125         LOG(ERROR) << "ClearMisc clear boot message to misc failed";
126         return false;
127     }
128     auto miscBlockDev = GetBlockDeviceByMountPoint(MISC_PATH);
129     if (miscBlockDev.empty()) {
130         LOG(INFO) << "cannot get block device of partition";
131         miscBlockDev = MISC_FILE;
132     }
133     LOG(INFO) << "ClearMisc::misc path : " << miscBlockDev;
134     auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(miscBlockDev.c_str(), "rb+"), fclose);
135     if (fp == nullptr) {
136         LOG(ERROR) << "WriteVersionCode fopen failed" << " : " << strerror(errno);
137         return false;
138     }
139     if (fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET) != 0) {
140         LOG(ERROR) << "ClearMisc fseek failed";
141         return false;
142     }
143     off_t clearOffset = 0;
144     if (fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) != 1) {
145         LOG(ERROR) << "ClearMisc write misc initOffset 0 failed" << " : " << strerror(errno);
146         return false;
147     }
148 
149     struct PartitionRecordInfo cleanPartition {};
150     for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset +=
151         sizeof(PartitionRecordInfo)) {
152         if (fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET) != 0) {
153             LOG(ERROR) << "ClearMisc fseek failed";
154             return false;
155         }
156         if (fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) != 1) {
157             LOG(ERROR) << "ClearMisc write misc cleanPartition failed" << " : " << strerror(errno);
158             return false;
159         }
160     }
161     return true;
162 }
163 
IsSDCardExist(const std::string & sdcardPath)164 bool IsSDCardExist(const std::string &sdcardPath)
165 {
166     // Record system error codes.
167     int save_errno = errno;
168     struct stat st {};
169     if (stat(sdcardPath.c_str(), &st) < 0) {
170         return false;
171     } else {
172         errno = save_errno;
173         return true;
174     }
175 }
176 
PostUpdater(bool clearMisc)177 void PostUpdater(bool clearMisc)
178 {
179     STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater";
180 
181     (void)SetupPartitions();
182     UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_INIT_EVENT);
183     // clear update misc partition.
184     if (clearMisc && !ClearMisc()) {
185         LOG(ERROR) << "PostUpdater clear misc failed";
186     }
187     if (!access(COMMAND_FILE, 0) && unlink(COMMAND_FILE) != 0) {
188         LOG(ERROR) << "Delete command failed";
189     }
190 
191     // delete updater tmp files
192     if (access(UPDATER_PATH, 0) == 0 && access(SDCARD_CARD_PATH, 0) != 0 && !DeleteUpdaterPath(UPDATER_PATH)) {
193         LOG(ERROR) << "DeleteUpdaterPath failed";
194     }
195     if (access(SDCARD_CARD_PATH, 0) == 0 && !DeleteUpdaterPath(SDCARD_CARD_PATH)) {
196         LOG(ERROR) << "Delete sdcard path failed";
197     }
198     if (access(Flashd::FLASHD_FILE_PATH, 0) == 0 && !DeleteUpdaterPath(Flashd::FLASHD_FILE_PATH)) {
199         LOG(ERROR) << "DeleteUpdaterPath failed";
200     }
201 
202     SaveLogs();
203 }
204 
InitMode(void) const205 void BootMode::InitMode(void) const
206 {
207     InitUpdaterLogger(modeName, TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH);
208 #ifdef UPDATER_BUILD_VARIANT_USER
209     SetLogLevel(INFO);
210 #else
211     SetLogLevel(DEBUG);
212 #endif
213     LoadFstab();
214     STAGE(UPDATE_STAGE_OUT) << "Start " << modeName;
215     SetParameter(modePara.c_str(), "1");
216 }
217 
IsUpdater(const UpdateMessage & boot)218 bool IsUpdater(const UpdateMessage &boot)
219 {
220     return !IsFlashd(boot) && strncmp(boot.command, "boot_updater", sizeof("boot_updater") - 1) == 0;
221 }
222 
IsFlashd(const UpdateMessage & boot)223 bool IsFlashd(const UpdateMessage &boot)
224 {
225     return strncmp(boot.update, "boot_flash", sizeof("boot_flash") - 1) == 0;
226 }
227 
GetBootModes(void)228 std::vector<BootMode> &GetBootModes(void)
229 {
230     static std::vector<BootMode> bootModes {};
231     return bootModes;
232 }
233 
RegisterMode(const BootMode & mode)234 void RegisterMode(const BootMode &mode)
235 {
236     GetBootModes().push_back(mode);
237 }
238 
SelectMode(const UpdateMessage & boot)239 std::optional<BootMode> SelectMode(const UpdateMessage &boot)
240 {
241     const auto &modes = GetBootModes();
242 
243     // select modes by bootMode.cond which would check misc message
244     auto it = std::find_if(modes.begin(), modes.end(), [&boot] (const auto &bootMode) {
245         if (bootMode.cond != nullptr && bootMode.cond(boot)) {
246             return true;
247         }
248         LOG(WARNING) << "condition for mode " << bootMode.modeName << " is not satisfied";
249         return false;
250     });
251     // misc check failed for each mode, then enter updater mode
252     if (it == modes.end() || it->entryFunc == nullptr) {
253         LOG(WARNING) << "find valid mode failed, enter updater Mode";
254         return std::nullopt;
255     }
256 
257     LOG(INFO) << "enter " << it->modeName << " mode";
258     return *it;
259 }
260 } // namespace Updater
261