1 /*
2 * Copyright (c) 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
16 #include "module_update_main.h"
17
18 #include <fcntl.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <thread>
22 #include <unistd.h>
23
24 #include "directory_ex.h"
25 #include "module_utils.h"
26 #include "hisysevent_manager.h"
27 #include "json_node.h"
28 #include "log/log.h"
29 #include "module_update_service.h"
30 #include "parameter.h"
31 #include "system_ability_definition.h"
32 #include "module_constants.h"
33 #include "module_update_consumer.h"
34 #include "module_update_producer.h"
35 #include "module_error_code.h"
36 #include "module_file.h"
37 #include "module_update.h"
38 #include "package/package.h"
39 #include "scope_guard.h"
40 #include "utils.h"
41 #include "unique_fd.h"
42
43 #ifdef WITH_SELINUX
44 #include <policycoreutils.h>
45 #endif // WITH_SELINUX
46
47 namespace OHOS {
48 namespace SysInstaller {
49 using namespace Updater;
50
51 namespace {
52 constexpr int32_t RETRY_TIMES_FOR_SAMGR = 10;
53 constexpr std::chrono::milliseconds MILLISECONDS_WAITING_SAMGR_ONE_TIME(100);
54 constexpr mode_t DIR_MODE = 0750;
55
56 static volatile sig_atomic_t g_exit = 0;
57
CreateModuleDirs(const std::string & hmpName)58 int32_t CreateModuleDirs(const std::string &hmpName)
59 {
60 if (!CreateDirIfNeeded(UPDATE_INSTALL_DIR, DIR_MODE)) {
61 LOG(ERROR) << "Failed to create install dir";
62 return ModuleErrorCode::ERR_INSTALL_FAIL;
63 }
64 #ifdef WITH_SELINUX
65 if (Restorecon(UPDATE_INSTALL_DIR) == -1) {
66 LOG(WARNING) << "restore " << UPDATE_INSTALL_DIR << " failed";
67 }
68 #endif // WITH_SELINUX
69 std::string hmpInstallDir = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
70 if (!CreateDirIfNeeded(hmpInstallDir, DIR_MODE)) {
71 LOG(ERROR) << "Failed to create hmp install dir " << hmpInstallDir;
72 return ModuleErrorCode::ERR_INSTALL_FAIL;
73 }
74 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
75 }
76
GetFileAllName(const std::string & path)77 std::string GetFileAllName(const std::string &path)
78 {
79 auto pos = path.find_last_of('/');
80 if (pos == std::string::npos) {
81 pos = path.find_last_of('\\');
82 if (pos == std::string::npos) {
83 return "";
84 }
85 }
86 return path.substr(pos + 1);
87 }
88
BackupFile(const std::string & file)89 bool BackupFile(const std::string &file)
90 {
91 std::string fileName = GetFileAllName(file);
92 std::string hmpName = GetHmpName(file);
93 if (fileName.empty() || hmpName.empty()) {
94 return true;
95 }
96 std::string destPath = std::string(UPDATE_BACKUP_DIR) + "/" + hmpName;
97 if (!CreateDirIfNeeded(destPath, DIR_MODE)) {
98 LOG(ERROR) << "Failed to create hmp dir " << destPath;
99 return false;
100 }
101 std::string destFile = destPath + "/" + fileName;
102 int ret = link(file.c_str(), destFile.c_str());
103 if (ret != 0) {
104 LOG(ERROR) << "Failed to link file " << file << " to dest " << destFile;
105 return false;
106 }
107 return true;
108 }
109 }
110
ModuleUpdateMain()111 ModuleUpdateMain::ModuleUpdateMain()
112 {
113 }
114
115 ModuleUpdateMain::~ModuleUpdateMain() = default;
116
DoHotInstall(ModuleUpdateStatus & status)117 bool ModuleUpdateMain::DoHotInstall(ModuleUpdateStatus &status)
118 {
119 if (!status.isHotInstall) {
120 if (status.type == COLD_APP_TYPE || status.type == COLD_MIX_TYPE) {
121 SetParameter(BMS_START_INSTALL, BMS_UPDATE);
122 }
123 return true;
124 }
125 LOG(INFO) << "DoHotInstall, hmpName=" << status.hmpName << " ;type=" << status.type;
126 if (status.type == HOT_APP_TYPE) {
127 return HotAppInstall(status);
128 } else if (status.type == HOT_SA_TYPE) {
129 HotSaInstall(status);
130 }
131 return true;
132 }
133
HotSaInstall(ModuleUpdateStatus & status)134 void ModuleUpdateMain::HotSaInstall(ModuleUpdateStatus &status)
135 {
136 if (!ModuleUpdate::GetInstance().DoModuleUpdate(status)) {
137 LOG(ERROR) << "HotSaInstall fail, hmpName=" << status.hmpName;
138 return;
139 }
140 RemoveSpecifiedDir(std::string(UPDATE_INSTALL_DIR) + "/" + status.hmpName);
141 }
142
HotAppInstall(ModuleUpdateStatus & status)143 bool ModuleUpdateMain::HotAppInstall(ModuleUpdateStatus &status)
144 {
145 ON_SCOPE_EXIT(rmdir) {
146 RemoveSpecifiedDir(std::string(UPDATE_INSTALL_DIR) + "/" + status.hmpName);
147 };
148 if (!ModuleUpdate::GetInstance().DoModuleUpdate(status)) {
149 LOG(ERROR) << "HotAppInstall fail, hmpName=" << status.hmpName;
150 HotAppInstallWhenUpdateFail(status);
151 return false;
152 }
153 std::string hmpPath = std::string(MODULE_ROOT_DIR) + "/" + status.hmpName;
154 if (InstallHmpBundle(hmpPath, false)) {
155 LOG(INFO) << "HotAppInstall, install app succ; hmpName=" << status.hmpName;
156 return true;
157 }
158 // remove mountPoint and redo ModuleUpdate; even remove fail, still revert.
159 (void)ModuleUpdate::GetInstance().RemoveMountPoint(status.hmpName);
160 Revert(status.hmpName, false);
161 FirstRevertInstallHotApp(status);
162 return false;
163 }
164
HotAppInstallWhenUpdateFail(ModuleUpdateStatus & status)165 void ModuleUpdateMain::HotAppInstallWhenUpdateFail(ModuleUpdateStatus &status)
166 {
167 std::string hmpPath = std::string(MODULE_ROOT_DIR) + "/" + status.hmpName;
168 // if /module_update/hmp exist, do not revert
169 if (CheckPathExists(hmpPath)) {
170 LOG(ERROR) << "Current module img is the same with last, don't revert; hmpName:" << status.hmpName;
171 return;
172 }
173 FirstRevertInstallHotApp(status);
174 }
175
FirstRevertInstallHotApp(ModuleUpdateStatus & status)176 void ModuleUpdateMain::FirstRevertInstallHotApp(ModuleUpdateStatus &status)
177 {
178 LOG(WARNING) << "First revert hot app, hmpName=" << status.hmpName;
179 std::string activeHmpPath = std::string(UPDATE_ACTIVE_DIR) + "/" + status.hmpName;
180 std::string hmpPath = std::string(MODULE_ROOT_DIR) + "/" + status.hmpName;
181 if (!ModuleUpdate::GetInstance().DoModuleUpdate(status)) {
182 LOG(ERROR) << "First revert fail, hmpName=" << status.hmpName;
183 SecondRevertInstallHotApp(status);
184 return;
185 }
186 if (InstallHmpBundle(hmpPath, true)) {
187 LOG(INFO) << "After first revert, install app succ; hmpName=" << status.hmpName;
188 return;
189 }
190 SecondRevertInstallHotApp(status);
191 }
192
SecondRevertInstallHotApp(ModuleUpdateStatus & status)193 void ModuleUpdateMain::SecondRevertInstallHotApp(ModuleUpdateStatus &status)
194 {
195 LOG(WARNING) << "Second revert hot app, hmpName=" << status.hmpName;
196 std::string activeHmpPath = std::string(UPDATE_ACTIVE_DIR) + "/" + status.hmpName;
197 std::string hmpPath = std::string(MODULE_ROOT_DIR) + "/" + status.hmpName;
198 if (!CheckPathExists(activeHmpPath) && CheckPathExists(hmpPath)) {
199 LOG(WARNING) << "current IMG is preinstall, force to install; hmpName:" << status.hmpName;
200 (void)InstallHmpBundle(hmpPath, true);
201 return;
202 }
203 (void)ModuleUpdate::GetInstance().RemoveMountPoint(status.hmpName);
204 Revert(status.hmpName, false);
205 (void)ModuleUpdate::GetInstance().DoModuleUpdate(status);
206 if (!CheckPathExists(hmpPath)) {
207 LOG(ERROR) << "HotApp, Second Revert hmpName: " << status.hmpName << " fail.";
208 return;
209 }
210 (void)InstallHmpBundle(hmpPath, true);
211 }
212
CheckHmpName(const std::string & hmpName)213 int32_t ModuleUpdateMain::CheckHmpName(const std::string &hmpName)
214 {
215 if (hmpName.empty()) {
216 LOG(ERROR) << "Failed to get hmpName=" << hmpName;
217 return ModuleErrorCode::ERR_INVALID_PATH;
218 }
219 if (hmpSet_.find(hmpName) == hmpSet_.end()) {
220 LOG(ERROR) << "Failed to install hmp without preInstall";
221 return ModuleErrorCode::ERR_INSTALL_FAIL;
222 }
223 int32_t ret = CreateModuleDirs(hmpName);
224 if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
225 RemoveSpecifiedDir(std::string(UPDATE_INSTALL_DIR) + "/" + hmpName);
226 return ret;
227 }
228 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
229 }
230
ReallyInstallModulePackage(const std::string & pkgPath,const sptr<ISysInstallerCallback> & updateCallback)231 int32_t ModuleUpdateMain::ReallyInstallModulePackage(const std::string &pkgPath,
232 const sptr<ISysInstallerCallback> &updateCallback)
233 {
234 std::string hmpName = GetFileName(pkgPath);
235 int32_t ret = CheckHmpName(hmpName);
236 if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
237 return ret;
238 }
239 std::string hmpDir = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
240 ON_SCOPE_EXIT(rmdir) {
241 RemoveSpecifiedDir(hmpDir);
242 };
243 std::string outPath = hmpDir + "/";
244 ret = ExtraPackageDir(pkgPath.c_str(), nullptr, nullptr, outPath.c_str());
245 if (ret != 0) {
246 LOG(ERROR) << "Failed to unpack hmp package " << pkgPath;
247 return ModuleErrorCode::ERR_INSTALL_FAIL;
248 }
249 std::vector<std::string> files;
250 GetDirFiles(hmpDir, files);
251 // for check hot hmp
252 ModuleUpdateStatus status;
253 status.hmpName = hmpName;
254 int index = 1;
255 for (auto &file : files) {
256 ret = InstallModuleFile(hmpName, file, status);
257 if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
258 return ret;
259 }
260 if (updateCallback != nullptr) {
261 int percent = static_cast<float>(index) / files.size() * 95; // 95 : 95% percent
262 updateCallback->OnUpgradeProgress(UPDATE_STATE_ONGOING, percent, "");
263 }
264 index++;
265 }
266 if (!BackupActiveModules(hmpName)) {
267 LOG(ERROR) << "Failed to backup active hmp: " << hmpName;
268 return ModuleErrorCode::ERR_INSTALL_FAIL;
269 }
270 CANCEL_SCOPE_EXIT_GUARD(rmdir);
271
272 // create avtive hmp dir finally, avoid to be backup.
273 std::string hmpActiveDir = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
274 if (!CreateDirIfNeeded(hmpActiveDir, DIR_MODE)) {
275 LOG(ERROR) << "Failed to create hmp active dir " << hmpActiveDir;
276 return ModuleErrorCode::ERR_INSTALL_FAIL;
277 }
278 if (!DoHotInstall(status)) {
279 sync();
280 return ModuleErrorCode::ERR_INSTALL_FAIL;
281 }
282 sync();
283 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
284 }
285
ValidateVersion(ModuleFile & installFile,const std::string & hmpName) const286 int32_t ModuleUpdateMain::ValidateVersion(ModuleFile &installFile, const std::string &hmpName) const
287 {
288 std::string preInstalledPath = std::string(MODULE_PREINSTALL_DIR) + "/" + hmpName + "/" + HMP_INFO_NAME;
289 std::unique_ptr<ModuleFile> preInstalledFile = ModuleFile::Open(preInstalledPath);
290 if (preInstalledFile == nullptr) {
291 LOG(ERROR) << "Invalid preinstalled file " << preInstalledPath;
292 return ModuleErrorCode::ERR_INSTALL_FAIL;
293 }
294 if (!ModuleFile::CompareVersion(installFile, *preInstalledFile)) {
295 LOG(ERROR) << "Installed version is lower than preInstall.";
296 return ModuleErrorCode::ERR_LOWER_VERSION;
297 }
298 if (!installFile.VerifyModuleVerity()) {
299 LOG(ERROR) << "Failed to verify install img: " << hmpName;
300 return ModuleErrorCode::ERR_VERIFY_SIGN_FAIL;
301 }
302
303 std::string activePath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName + "/" + HMP_INFO_NAME;
304 if (!Utils::IsFileExist(activePath)) {
305 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
306 }
307 std::unique_ptr<ModuleFile> activeFile = ModuleFile::Open(activePath);
308 if (activeFile == nullptr) {
309 LOG(WARNING) << "Invalid active file " << activePath;
310 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
311 }
312 if (!ModuleFile::CompareVersion(installFile, *activeFile)) {
313 LOG(ERROR) << "Installed version is lower than active.";
314 return ModuleErrorCode::ERR_LOWER_VERSION;
315 }
316 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
317 }
318
InstallModuleFile(const std::string & hmpName,const std::string & file,ModuleUpdateStatus & status) const319 int32_t ModuleUpdateMain::InstallModuleFile(const std::string &hmpName, const std::string &file,
320 ModuleUpdateStatus &status) const
321 {
322 if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
323 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
324 }
325 std::string fileName = GetFileName(file);
326 if (fileName.empty()) {
327 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
328 }
329 // verify first, then open module file.
330 if (VerifyModulePackageSign(file) != 0) {
331 LOG(ERROR) << "Verify sign failed " << file;
332 return ModuleErrorCode::ERR_VERIFY_SIGN_FAIL;
333 }
334
335 std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
336 if (moduleFile == nullptr) {
337 LOG(ERROR) << "Wrong module file " << file << " in hmp package " << hmpName;
338 return ModuleErrorCode::ERR_INSTALL_FAIL;
339 }
340 if (!moduleFile->GetImageStat().has_value()) {
341 LOG(ERROR) << "Could not install empty module package " << file;
342 return ModuleErrorCode::ERR_INSTALL_FAIL;
343 }
344 if (ValidateVersion(*moduleFile, hmpName) != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
345 return ModuleErrorCode::ERR_INSTALL_FAIL;
346 }
347 status.type = moduleFile->GetHmpPackageType();
348 status.isHotInstall = IsHotHmpPackage(static_cast<int32_t>(status.type));
349 moduleFile->ClearVerifiedData();
350 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
351 }
352
UninstallModulePackage(const std::string & hmpName)353 int32_t ModuleUpdateMain::UninstallModulePackage(const std::string &hmpName)
354 {
355 LOG(INFO) << "UninstallModulePackage " << hmpName;
356 int ret = ModuleErrorCode::MODULE_UPDATE_SUCCESS;
357 if (hmpName.empty() || hmpSet_.find(hmpName) == hmpSet_.end()) {
358 return ModuleErrorCode::ERR_INVALID_PATH;
359 }
360 std::vector<std::string> uninstallDir {UPDATE_INSTALL_DIR, UPDATE_ACTIVE_DIR, UPDATE_BACKUP_DIR};
361 std::string hmpDir = "/" + hmpName;
362 bool hmpIsValid = false;
363 for (const auto &iter : uninstallDir) {
364 std::string dir = iter + hmpDir;
365 if (!CheckPathExists(dir)) {
366 continue;
367 }
368 hmpIsValid = true;
369 if (!ForceRemoveDirectory(dir)) {
370 LOG(ERROR) << "Failed to remove " << dir;
371 ret = ModuleErrorCode::ERR_UNINSTALL_FAIL;
372 }
373 }
374 if (!hmpIsValid) {
375 ret = ModuleErrorCode::ERR_INVALID_PATH;
376 }
377 return ret;
378 }
379
GetModulePackageInfo(const std::string & hmpName,std::list<ModulePackageInfo> & modulePackageInfos)380 int32_t ModuleUpdateMain::GetModulePackageInfo(const std::string &hmpName,
381 std::list<ModulePackageInfo> &modulePackageInfos)
382 {
383 LOG(INFO) << "GetModulePackageInfo " << hmpName;
384 if (hmpName.empty()) {
385 for (auto &hmp : hmpSet_) {
386 CollectModulePackageInfo(hmp, modulePackageInfos);
387 }
388 } else if (find(hmpSet_.begin(), hmpSet_.end(), hmpName) != hmpSet_.end()) {
389 CollectModulePackageInfo(hmpName, modulePackageInfos);
390 } else {
391 LOG(ERROR) << hmpName << " not exist in hmpSet";
392 return ModuleErrorCode::MODULE_UPDATE_FAIL;
393 }
394 return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
395 }
CollectModulePackageInfo(const std::string & hmpName,std::list<ModulePackageInfo> & modulePackageInfos) const396 void ModuleUpdateMain::CollectModulePackageInfo(const std::string &hmpName,
397 std::list<ModulePackageInfo> &modulePackageInfos) const
398 {
399 if (hmpName.empty()) {
400 return;
401 }
402 std::string installHmpPath = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
403 std::string activeHmpPath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
404 if (!CheckPathExists(installHmpPath) && !CheckPathExists(activeHmpPath)) {
405 return;
406 }
407 std::vector<std::string> files;
408 GetDirFiles(installHmpPath, files);
409 GetDirFiles(activeHmpPath, files);
410 for (auto &file : files) {
411 if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
412 continue;
413 }
414 std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
415 if (moduleFile == nullptr) {
416 return;
417 }
418 modulePackageInfos.emplace_back(std::move(moduleFile->GetVersionInfo()));
419 }
420 }
421
ExitModuleUpdate()422 void ModuleUpdateMain::ExitModuleUpdate()
423 {
424 LOG(INFO) << "ExitModuleUpdate";
425 Stop();
426 }
427
GetHmpVersion(const std::string & hmpPath,HmpVersionInfo & versionInfo)428 bool ModuleUpdateMain::GetHmpVersion(const std::string &hmpPath, HmpVersionInfo &versionInfo)
429 {
430 LOG(INFO) << "GetHmpVersion " << hmpPath;
431 std::string packInfoPath = hmpPath + "/" + HMP_INFO_NAME;
432 if (!Utils::IsFileExist(packInfoPath)) {
433 LOG(ERROR) << "pack.info is not exist: " << packInfoPath;
434 return false;
435 }
436 if (!StartsWith(packInfoPath, MODULE_PREINSTALL_DIR) &&
437 VerifyModulePackageSign(packInfoPath) != 0) {
438 LOG(ERROR) << "Verify sign failed " << packInfoPath;
439 return false;
440 }
441 std::string packInfo = GetContentFromZip(packInfoPath, PACK_INFO_NAME);
442 JsonNode root(packInfo);
443 const JsonNode &package = root["package"];
444 std::optional<std::string> name = package["name"].As<std::string>();
445 if (!name.has_value()) {
446 LOG(ERROR) << "count get name val";
447 return false;
448 }
449
450 std::optional<std::string> version = package["version"].As<std::string>();
451 if (!version.has_value()) {
452 LOG(ERROR) << "count get version val";
453 return false;
454 }
455
456 const JsonNode &laneInfoNode = package["laneInfo"];
457 std::optional<std::string> compatibleVersion = laneInfoNode["compatibleVersion"].As<std::string>();
458 if (!compatibleVersion.has_value()) {
459 LOG(ERROR) << "count get compatibleVersion val";
460 return false;
461 }
462
463 std::optional<std::string> laneCode = laneInfoNode["laneCode"].As<std::string>();
464 if (!laneCode.has_value()) {
465 LOG(ERROR) << "count get laneCode val";
466 return false;
467 }
468
469 versionInfo.name = name.value();
470 versionInfo.version = version.value();
471 versionInfo.compatibleVersion = compatibleVersion.value();
472 versionInfo.laneCode = laneCode.value();
473 return true;
474 }
475
ParseHmpVersionInfo(std::vector<HmpVersionInfo> & versionInfos,const HmpVersionInfo & preInfo,const HmpVersionInfo & actInfo)476 void ModuleUpdateMain::ParseHmpVersionInfo(std::vector<HmpVersionInfo> &versionInfos, const HmpVersionInfo &preInfo,
477 const HmpVersionInfo &actInfo)
478 {
479 if (preInfo.version.size() == 0 && actInfo.version.size() == 0) {
480 LOG(WARNING) << "version is empty";
481 return;
482 }
483
484 if (actInfo.version.size() == 0) {
485 LOG(INFO) << "add preinstaller info";
486 versionInfos.emplace_back(preInfo);
487 return;
488 }
489 std::vector<std::string> preVersion {};
490 std::vector<std::string> actVersion {};
491 // version: xxx-d01 M.S.F.B
492 if (!ParseVersion(preInfo.version, " ", preVersion)) {
493 LOG(ERROR) << "Parse preVersion failed.";
494 return;
495 }
496
497 if (!ParseVersion(actInfo.version, " ", actVersion)) {
498 LOG(WARNING) << "Parse actVersion failed.";
499 versionInfos.emplace_back(preInfo);
500 return;
501 }
502
503 if (CompareHmpVersion(preVersion, actVersion)) {
504 LOG(INFO) << "add active info";
505 versionInfos.emplace_back(actInfo);
506 } else {
507 LOG(INFO) << "add preinstaller info";
508 versionInfos.emplace_back(preInfo);
509 }
510 }
511
GetHmpVersionInfo()512 std::vector<HmpVersionInfo> ModuleUpdateMain::GetHmpVersionInfo()
513 {
514 LOG(INFO) << "GetHmpVersionInfo";
515 std::vector<HmpVersionInfo> versionInfos {};
516 ScanPreInstalledHmp();
517 for (auto &hmp : hmpSet_) {
518 std::string preInstallHmpPath = std::string(MODULE_PREINSTALL_DIR) + "/" + hmp;
519 std::string activeHmpPath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmp;
520 LOG(INFO) << "preInstallHmpPath:" << preInstallHmpPath << " activeHmpPath:" << activeHmpPath;
521 HmpVersionInfo actinfo {};
522 HmpVersionInfo preinfo {};
523 (void)GetHmpVersion(preInstallHmpPath, preinfo);
524 (void)GetHmpVersion(activeHmpPath, actinfo);
525 ParseHmpVersionInfo(versionInfos, preinfo, actinfo);
526 }
527 return versionInfos;
528 }
529
SaveInstallerResult(const std::string & hmpPath,int result,const std::string & resultInfo,const Timer & timer)530 void ModuleUpdateMain::SaveInstallerResult(const std::string &hmpPath, int result,
531 const std::string &resultInfo, const Timer &timer)
532 {
533 LOG(INFO) << "hmpPath:" << hmpPath << " result:" << result << " resultInfo:" << resultInfo;
534 UniqueFd fd(open(MODULE_RESULT_PATH, O_APPEND | O_RDWR | O_CREAT | O_CLOEXEC));
535 if (fd.Get() == -1) {
536 LOG(ERROR) << "Failed to open file";
537 return;
538 }
539 constexpr mode_t mode = 0755; // 0755 : rwx-r-x-r-x
540 if (chmod(MODULE_RESULT_PATH, mode) != 0) {
541 LOG(ERROR) << "Could not chmod " << MODULE_RESULT_PATH;
542 }
543 std::string writeInfo = hmpPath + ";" + std::to_string(result) + ";" +
544 resultInfo + "|" + std::to_string(timer.duration().count()) + "\n";
545 if (CheckAndUpdateRevertResult(hmpPath, writeInfo, "revert")) {
546 return;
547 }
548 if (write(fd, writeInfo.data(), writeInfo.length()) <= 0) {
549 LOG(WARNING) << "write result file failed, err:" << errno;
550 }
551 fsync(fd.Get());
552 }
553
BackupActiveModules(const std::string & hmpName) const554 bool ModuleUpdateMain::BackupActiveModules(const std::string &hmpName) const
555 {
556 std::string activePath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
557 if (!CheckPathExists(activePath)) {
558 LOG(INFO) << "Nothing to backup, path: " << activePath;
559 return true;
560 }
561 std::string backupPath = std::string(UPDATE_BACKUP_DIR) + "/" + hmpName;
562 if (CheckPathExists(backupPath)) {
563 if (!ForceRemoveDirectory(backupPath)) {
564 LOG(ERROR) << "Failed to remove backup dir:" << backupPath;
565 return false;
566 }
567 }
568 if (!CreateDirIfNeeded(backupPath, DIR_MODE)) {
569 LOG(ERROR) << "Failed to create backup dir:" << backupPath;
570 return false;
571 }
572
573 std::vector<std::string> activeFiles;
574 GetDirFiles(activePath, activeFiles);
575 ON_SCOPE_EXIT(rmdir) {
576 if (!ForceRemoveDirectory(backupPath)) {
577 LOG(WARNING) << "Failed to remove backup dir when backup failed";
578 }
579 };
580 for (const auto &file : activeFiles) {
581 if (!BackupFile(file)) {
582 return false;
583 }
584 }
585
586 CANCEL_SCOPE_EXIT_GUARD(rmdir);
587 return true;
588 }
589
ScanPreInstalledHmp()590 void ModuleUpdateMain::ScanPreInstalledHmp()
591 {
592 std::vector<std::string> files;
593 GetDirFiles(MODULE_PREINSTALL_DIR, files);
594 for (auto &file : files) {
595 if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
596 continue;
597 }
598 std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
599 if (moduleFile == nullptr) {
600 continue;
601 }
602 std::string hmpName = GetHmpName(file);
603 if (hmpName.empty()) {
604 continue;
605 }
606 std::unique_lock<std::mutex> locker(mlock_);
607 hmpSet_.emplace(hmpName);
608 for (const auto &saInfo : moduleFile->GetVersionInfo().saInfoList) {
609 saIdHmpMap_.emplace(saInfo.saId, hmpName);
610 }
611 }
612 }
613
GetSystemAbilityManager()614 sptr<ISystemAbilityManager> &ModuleUpdateMain::GetSystemAbilityManager()
615 {
616 if (samgr_ != nullptr) {
617 return samgr_;
618 }
619 int32_t times = RETRY_TIMES_FOR_SAMGR;
620 constexpr int32_t duration = std::chrono::microseconds(MILLISECONDS_WAITING_SAMGR_ONE_TIME).count();
621 while (times > 0) {
622 times--;
623 samgr_ = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
624 if (samgr_ == nullptr) {
625 LOG(INFO) << "waiting for samgr";
626 usleep(duration);
627 } else {
628 break;
629 }
630 }
631 return samgr_;
632 }
633
Start()634 void ModuleUpdateMain::Start()
635 {
636 LOG(INFO) << "ModuleUpdateMain Start";
637 ModuleUpdateQueue queue;
638 ModuleUpdateProducer producer(queue, saIdHmpMap_, hmpSet_, g_exit);
639 ModuleUpdateConsumer consumer(queue, saIdHmpMap_, g_exit);
640 std::thread produceThread([&producer] {
641 producer.Run();
642 });
643 std::thread consumeThread([&consumer] {
644 consumer.Run();
645 });
646 consumeThread.join();
647 produceThread.join();
648 LOG(INFO) << "module update main exit";
649 }
650
Stop()651 void ModuleUpdateMain::Stop()
652 {
653 LOG(INFO) << "ModuleUpdateMain Stop";
654 g_exit = 1;
655 }
656 } // namespace SysInstaller
657 } // namespace OHOS