• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_service.h"
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 
22 #include "directory_ex.h"
23 #include "init_reboot.h"
24 #include "json_node.h"
25 #include "log/log.h"
26 #include "module_constants.h"
27 #include "module_error_code.h"
28 #include "module_file.h"
29 #include "module_utils.h"
30 #include "package/package.h"
31 #include "scope_guard.h"
32 #include "system_ability_definition.h"
33 #include "utils.h"
34 #include "unique_fd.h"
35 #ifdef WITH_SELINUX
36 #include <policycoreutils.h>
37 #endif // WITH_SELINUX
38 
39 namespace OHOS {
40 namespace SysInstaller {
41 using namespace Updater;
42 
43 namespace {
44 constexpr mode_t DIR_MODE = 0750;
45 constexpr mode_t ALL_PERMISSIONS = 0777;
46 
CreateModuleDirs(const std::string & hmpName)47 int32_t CreateModuleDirs(const std::string &hmpName)
48 {
49     if (!CreateDirIfNeeded(UPDATE_INSTALL_DIR, DIR_MODE)) {
50         LOG(ERROR) << "Failed to create install dir";
51         return ModuleErrorCode::ERR_INSTALL_FAIL;
52     }
53 #ifdef WITH_SELINUX
54     if (Restorecon(UPDATE_INSTALL_DIR) == -1) {
55         LOG(WARNING) << "restore " << UPDATE_INSTALL_DIR << " failed";
56     }
57 #endif // WITH_SELINUX
58     std::string hmpInstallDir = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
59     if (!CreateDirIfNeeded(hmpInstallDir, DIR_MODE)) {
60         LOG(ERROR) << "Failed to create hmp install dir " << hmpInstallDir;
61         return ModuleErrorCode::ERR_INSTALL_FAIL;
62     }
63     std::string hmpActiveDir = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
64     if (!CreateDirIfNeeded(hmpActiveDir, DIR_MODE)) {
65         LOG(ERROR) << "Failed to create hmp active dir " << hmpActiveDir;
66         return ModuleErrorCode::ERR_INSTALL_FAIL;
67     }
68     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
69 }
70 
ClearModuleDirs(const std::string & hmpName)71 bool ClearModuleDirs(const std::string &hmpName)
72 {
73     std::string hmpInstallDir = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
74     return ForceRemoveDirectory(hmpInstallDir);
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 
ModuleUpdateService()111 ModuleUpdateService::ModuleUpdateService() : SystemAbility(MODULE_UPDATE_SERVICE_ID, true)
112 {
113     LOG(INFO) << "ModuleUpdateService begin";
114 }
115 
~ModuleUpdateService()116 ModuleUpdateService::~ModuleUpdateService()
117 {
118     LOG(INFO) << "ModuleUpdateService end";
119 }
120 
InstallModulePackage(const std::string & pkgPath)121 int32_t ModuleUpdateService::InstallModulePackage(const std::string &pkgPath)
122 {
123     LOG(INFO) << "InstallModulePackage " << pkgPath;
124     std::string realPath;
125     if (!CheckFileSuffix(pkgPath, HMP_PACKAGE_SUFFIX) || !PathToRealPath(pkgPath, realPath)) {
126         LOG(ERROR) << "Invalid package path " << pkgPath;
127         return ModuleErrorCode::ERR_INVALID_PATH;
128     }
129     return ReallyInstallModulePackage(realPath, nullptr);
130 }
131 
ReallyInstallModulePackage(const std::string & pkgPath,const sptr<ISysInstallerCallback> & updateCallback)132 int32_t ModuleUpdateService::ReallyInstallModulePackage(const std::string &pkgPath,
133     const sptr<ISysInstallerCallback> &updateCallback)
134 {
135     std::string hmpName = GetFileName(pkgPath);
136     if (hmpName.empty()) {
137         LOG(ERROR) << "Failed to get hmp name " << pkgPath;
138         return ModuleErrorCode::ERR_INVALID_PATH;
139     }
140     if (hmpSet_.find(hmpName) == hmpSet_.end()) {
141         LOG(ERROR) << "Failed to install hmp without preInstall";
142         return ModuleErrorCode::ERR_INSTALL_FAIL;
143     }
144     int32_t ret = CreateModuleDirs(hmpName);
145     if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
146         ClearModuleDirs(hmpName);
147         return ret;
148     }
149     ON_SCOPE_EXIT(rmdir) {
150         if (!ClearModuleDirs(hmpName)) {
151             LOG(WARNING) << "Failed to remove " << hmpName;
152         }
153     };
154     std::string hmpDir = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
155     std::string outPath = hmpDir + "/";
156     ret = ExtraPackageDir(pkgPath.c_str(), nullptr, nullptr, outPath.c_str());
157     if (ret != 0) {
158         LOG(ERROR) << "Failed to unpack hmp package " << pkgPath;
159         return ModuleErrorCode::ERR_INSTALL_FAIL;
160     }
161     std::vector<std::string> files;
162     GetDirFiles(hmpDir, files);
163     int index = 1;
164     for (auto &file : files) {
165         ret = InstallModuleFile(hmpName, file);
166         if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
167             return ret;
168         }
169         if (updateCallback != nullptr) {
170             int percent = static_cast<float>(index) / files.size() * 95;  // 95 : 95% percent
171             updateCallback->OnUpgradeProgress(UPDATE_STATE_ONGOING, percent, "");
172         }
173         index++;
174     }
175     if (!BackupActiveModules()) {
176         LOG(ERROR) << "Failed to backup active modules";
177         return ModuleErrorCode::ERR_INSTALL_FAIL;
178     }
179     CANCEL_SCOPE_EXIT_GUARD(rmdir);
180     sync();
181     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
182 }
183 
InstallModuleFile(const std::string & hmpName,const std::string & file) const184 int32_t ModuleUpdateService::InstallModuleFile(const std::string &hmpName, const std::string &file) const
185 {
186     if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
187         return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
188     }
189     std::string fileName = GetFileName(file);
190     if (fileName.empty()) {
191         return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
192     }
193     std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
194     if (moduleFile == nullptr) {
195         LOG(ERROR) << "Wrong module file " << file << " in hmp package " << hmpName;
196         return ModuleErrorCode::ERR_INSTALL_FAIL;
197     }
198     if (!moduleFile->GetImageStat().has_value()) {
199         LOG(ERROR) << "Could not install empty module package " << file;
200         return ModuleErrorCode::ERR_INSTALL_FAIL;
201     }
202     if (saIdHmpMap_.find(moduleFile->GetSaId()) == saIdHmpMap_.end()) {
203         LOG(ERROR) << "Could not update module file " << file << " without preInstalled";
204         return ModuleErrorCode::ERR_INSTALL_FAIL;
205     }
206     std::string preInstalledHmp = saIdHmpMap_.at(moduleFile->GetSaId());
207     if (preInstalledHmp != hmpName) {
208         LOG(ERROR) << "Module file " << file << " should be in hmp " << preInstalledHmp;
209         return ModuleErrorCode::ERR_INSTALL_FAIL;
210     }
211     if (VerifyModulePackageSign(file) != 0) {
212         LOG(ERROR) << "Verify sign failed " << file;
213         return ModuleErrorCode::ERR_VERIFY_SIGN_FAIL;
214     }
215 
216     std::string preInstalledPath = std::string(MODULE_PREINSTALL_DIR) + "/" + hmpName + "/" + fileName
217         + MODULE_PACKAGE_SUFFIX;
218     std::unique_ptr<ModuleFile> preInstalledFile = ModuleFile::Open(preInstalledPath);
219     if (preInstalledFile == nullptr) {
220         LOG(ERROR) << "Invalid preinstalled file " << preInstalledPath;
221         return ModuleErrorCode::ERR_INSTALL_FAIL;
222     }
223     if (!ModuleFile::CompareVersion(*moduleFile, *preInstalledFile)) {
224         LOG(ERROR) << "Installed lower version of " << file;
225         return ModuleErrorCode::ERR_LOWER_VERSION;
226     }
227     if (!moduleFile->VerifyModuleVerity(preInstalledFile->GetPublicKey())) {
228         LOG(ERROR) << "Failed to verify module verity " << file;
229         return ModuleErrorCode::ERR_VERIFY_SIGN_FAIL;
230     }
231     moduleFile->ClearVerifiedData();
232     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
233 }
234 
UninstallModulePackage(const std::string & hmpName)235 int32_t ModuleUpdateService::UninstallModulePackage(const std::string &hmpName)
236 {
237     LOG(INFO) << "UninstallModulePackage " << hmpName;
238     int ret = ModuleErrorCode::MODULE_UPDATE_SUCCESS;
239     if (hmpName.empty() || hmpSet_.find(hmpName) == hmpSet_.end()) {
240         return ModuleErrorCode::ERR_INVALID_PATH;
241     }
242     std::vector<std::string> uninstallDir {UPDATE_INSTALL_DIR, UPDATE_ACTIVE_DIR, UPDATE_BACKUP_DIR};
243     std::string hmpDir = "/" + hmpName;
244     bool hmpIsValid = false;
245     for (const auto &iter : uninstallDir) {
246         std::string dir = iter + hmpDir;
247         if (!CheckPathExists(dir)) {
248             continue;
249         }
250         hmpIsValid = true;
251         if (!ForceRemoveDirectory(dir)) {
252             LOG(ERROR) << "Failed to remove " << dir;
253             ret = ModuleErrorCode::ERR_UNINSTALL_FAIL;
254         }
255     }
256     if (!hmpIsValid) {
257         ret = ModuleErrorCode::ERR_INVALID_PATH;
258     }
259     return ret;
260 }
261 
GetModulePackageInfo(const std::string & hmpName,std::list<ModulePackageInfo> & modulePackageInfos)262 int32_t ModuleUpdateService::GetModulePackageInfo(const std::string &hmpName,
263     std::list<ModulePackageInfo> &modulePackageInfos)
264 {
265     LOG(INFO) << "GetModulePackageInfo " << hmpName;
266     if (hmpName.empty()) {
267         for (auto &hmp : hmpSet_) {
268             CollectModulePackageInfo(hmp, modulePackageInfos);
269         }
270     } else {
271         CollectModulePackageInfo(hmpName, modulePackageInfos);
272     }
273     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
274 }
275 
CollectModulePackageInfo(const std::string & hmpName,std::list<ModulePackageInfo> & modulePackageInfos) const276 void ModuleUpdateService::CollectModulePackageInfo(const std::string &hmpName,
277     std::list<ModulePackageInfo> &modulePackageInfos) const
278 {
279     if (hmpName.empty()) {
280         return;
281     }
282     std::string installHmpPath = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
283     std::string activeHmpPath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
284     if (!CheckPathExists(installHmpPath) && !CheckPathExists(activeHmpPath)) {
285         return;
286     }
287     std::vector<std::string> files;
288     GetDirFiles(installHmpPath, files);
289     GetDirFiles(activeHmpPath, files);
290     ModulePackageInfo info;
291     info.hmpName = hmpName;
292     for (auto &file : files) {
293         if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
294             continue;
295         }
296         std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
297         if (moduleFile == nullptr) {
298             continue;
299         }
300         SaInfo saInfo;
301         saInfo.saName = moduleFile->GetSaName();
302         saInfo.saId = moduleFile->GetSaId();
303         saInfo.version = moduleFile->GetVersionInfo();
304         info.saInfoList.emplace_back(std::move(saInfo));
305     }
306     modulePackageInfos.emplace_back(std::move(info));
307 }
308 
ReportModuleUpdateStatus(const ModuleUpdateStatus & status)309 int32_t ModuleUpdateService::ReportModuleUpdateStatus(const ModuleUpdateStatus &status)
310 {
311     LOG(INFO) << "ReportModuleUpdateStatus process=" << status.process;
312     if (status.process.empty()) {
313         LOG(ERROR) << "empty process name";
314         return ModuleErrorCode::ERR_REPORT_STATUS_FAIL;
315     }
316     std::unordered_set<std::string> hmpSet;
317     for (const auto &iter : status.saStatusList) {
318         ProcessSaStatus(iter, hmpSet);
319     }
320     processHmpMap_.emplace(status.process, hmpSet);
321     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
322 }
323 
ExitModuleUpdate()324 int32_t ModuleUpdateService::ExitModuleUpdate()
325 {
326     LOG(INFO) << "ExitModuleUpdate";
327     exit(0);
328 }
329 
GetHmpVersion(const std::string & hmpPath,HmpVersionInfo & versionInfo)330 bool ModuleUpdateService::GetHmpVersion(const std::string &hmpPath, HmpVersionInfo &versionInfo)
331 {
332     LOG(INFO) << "GetHmpVersion " << hmpPath;
333     std::string packInfoPath = hmpPath + "/" + PACK_INFO_NAME;
334     if (VerifyModulePackageSign(packInfoPath) != 0) {
335         LOG(ERROR) << "Verify sign failed " << packInfoPath;
336         return false;
337     }
338     JsonNode root(std::filesystem::path { packInfoPath });
339     const JsonNode &package = root["package"];
340     std::optional<std::string> name = package["name"].As<std::string>();
341     if (!name.has_value()) {
342         LOG(ERROR) << "count get name val";
343         return false;
344     }
345 
346     std::optional<std::string> version = package["version"].As<std::string>();
347     if (!version.has_value()) {
348         LOG(ERROR) << "count get version val";
349         return false;
350     }
351 
352     const JsonNode &laneInfoNode = package["laneInfo"];
353     std::optional<std::string> compatibleVersion = laneInfoNode["compatibleVersion"].As<std::string>();
354     if (!compatibleVersion.has_value()) {
355         LOG(ERROR) << "count get compatibleVersion val";
356         return false;
357     }
358 
359     std::optional<std::string> laneCode = laneInfoNode["laneCode"].As<std::string>();
360     if (!laneCode.has_value()) {
361         LOG(ERROR) << "count get laneCode val";
362         return false;
363     }
364 
365     versionInfo.name = name.value();
366     versionInfo.version = version.value();
367     versionInfo.compatibleVersion = compatibleVersion.value();
368     versionInfo.laneCode = laneCode.value();
369     return true;
370 }
371 
ParseHmpVersionInfo(std::vector<HmpVersionInfo> & versionInfos,const HmpVersionInfo & preInfo,const HmpVersionInfo & actInfo)372 void ModuleUpdateService::ParseHmpVersionInfo(std::vector<HmpVersionInfo> &versionInfos, const HmpVersionInfo &preInfo,
373     const HmpVersionInfo &actInfo)
374 {
375     if (preInfo.version.size() == 0 && actInfo.version.size() == 0) {
376         LOG(WARNING) << "version is empty";
377         return;
378     }
379 
380     if (actInfo.version.size() == 0) {
381         LOG(INFO) << "add preinstaller info";
382         versionInfos.emplace_back(preInfo);
383         return;
384     }
385     std::vector<std::string> preVersion {};
386     std::vector<std::string> actVersion {};
387     // version: xxx-d01 4.5.10.100
388     if (!ParseVersion(preInfo.version, " ", preVersion) || !ParseVersion(actInfo.version, " ", actVersion)) {
389         LOG(ERROR) << "ParseVersion failed";
390         return;
391     }
392 
393     if (ComparePackInfoVer(preVersion, actVersion)) {
394         LOG(INFO) << "add active info";
395         versionInfos.emplace_back(actInfo);
396     } else {
397         LOG(INFO) << "add preinstaller info";
398         versionInfos.emplace_back(preInfo);
399     }
400 }
401 
GetHmpVersionInfo()402 std::vector<HmpVersionInfo> ModuleUpdateService::GetHmpVersionInfo()
403 {
404     LOG(INFO) << "GetHmpVersionInfo";
405     std::vector<HmpVersionInfo> versionInfos {};
406     ScanPreInstalledHmp();
407     for (auto &hmp : hmpSet_) {
408         std::string preInstallHmpPath = std::string(MODULE_PREINSTALL_DIR) + "/" + hmp;
409         std::string activeHmpPath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmp;
410         LOG(INFO) << "preInstallHmpPath:" << preInstallHmpPath << " activeHmpPath:" << activeHmpPath;
411         HmpVersionInfo actinfo {};
412         HmpVersionInfo preinfo {};
413         (void)GetHmpVersion(preInstallHmpPath, preinfo);
414         (void)GetHmpVersion(activeHmpPath, actinfo);
415         ParseHmpVersionInfo(versionInfos, preinfo, actinfo);
416     }
417     return versionInfos;
418 }
419 
SaveInstallerResult(const std::string & hmpPath,int result,const std::string & resultInfo)420 void ModuleUpdateService::SaveInstallerResult(const std::string &hmpPath, int result, const std::string &resultInfo)
421 {
422     LOG(INFO) << "hmpPath:" << hmpPath << " result:" << result << " resultInfo:" << resultInfo;
423     UniqueFd fd(open(MODULE_RESULT_PATH, O_APPEND | O_RDWR | O_CREAT | O_CLOEXEC));
424     if (fd.Get() == -1) {
425         LOG(ERROR) << "Failed to open file";
426         return;
427     }
428     constexpr mode_t mode = 0755; // 0755 : rwx-r-x-r-x
429     if (chmod(MODULE_RESULT_PATH, mode) != 0) {
430         LOG(ERROR) << "Could not chmod " << MODULE_RESULT_PATH;
431     }
432     std::string writeInfo = hmpPath + ";" + std::to_string(result) + ";" + resultInfo + "\n";
433     if (write(fd, writeInfo.data(), writeInfo.length()) <= 0) {
434         LOG(WARNING) << "write result file failed, err:" << errno;
435     }
436     fsync(fd.Get());
437 }
438 
StartUpdateHmpPackage(const std::string & path,const sptr<ISysInstallerCallback> & updateCallback)439 int32_t ModuleUpdateService::StartUpdateHmpPackage(const std::string &path,
440     const sptr<ISysInstallerCallback> &updateCallback)
441 {
442     int32_t ret = -1;
443     ON_SCOPE_EXIT(saveResult) {
444         SaveInstallerResult(path, ret, std::to_string(ret));
445         updateCallback->OnUpgradeProgress(ret == 0 ? UPDATE_STATE_SUCCESSFUL : UPDATE_STATE_FAILED,
446             100, ""); // 100 : 100% percent
447     };
448     LOG(INFO) << "StartUpdateHmpPackage " << path;
449     if (updateCallback == nullptr) {
450         LOG(ERROR) << "StartUpdateHmpPackage updateCallback null";
451         ret = ModuleErrorCode::ERR_INVALID_PATH;
452         return ret;
453     }
454 
455     updateCallback->OnUpgradeProgress(UPDATE_STATE_ONGOING, 0, "");
456     if (VerifyModulePackageSign(path) != 0) {
457         LOG(ERROR) << "Verify sign failed " << path;
458         ret = ModuleErrorCode::ERR_VERIFY_SIGN_FAIL;
459         return ret;
460     }
461 
462     ret = InstallModulePackage(path);
463     return ret;
464 }
465 
GetHmpUpdateResult()466 std::vector<HmpUpdateInfo> ModuleUpdateService::GetHmpUpdateResult()
467 {
468     LOG(INFO) << "GetHmpUpdateResult";
469     std::vector<HmpUpdateInfo> updateInfo {};
470     std::ifstream ifs { MODULE_RESULT_PATH };
471     if (!ifs.is_open()) {
472         LOG(ERROR) << "open " << MODULE_RESULT_PATH << " failed";
473         return updateInfo;
474     }
475     std::string resultInfo {std::istreambuf_iterator<char> {ifs}, {}};
476     std::vector<std::string> results {};
477     SplitStr(resultInfo, "\n", results);
478     for (auto &result : results) {
479         HmpUpdateInfo tmpUpdateInfo {};
480         std::vector<std::string> signalResult {};
481         SplitStr(result, ";", signalResult);
482         if (signalResult.size() < 3) { // 3: pkg; result; result info
483             LOG(ERROR) << "parse " << result << " failed";
484             continue;
485         }
486         tmpUpdateInfo.path = signalResult[0];
487         tmpUpdateInfo.result = stoi(signalResult[1]);
488         tmpUpdateInfo.resultMsg = signalResult[2]; // 2: result info
489         bool isFind = false;
490         for (auto &iter : updateInfo) {
491             if (iter.path.find(tmpUpdateInfo.path) != std::string::npos) {
492                 iter.result = tmpUpdateInfo.result;
493                 iter.resultMsg = tmpUpdateInfo.resultMsg;
494                 isFind = true;
495                 break;
496             }
497         }
498         if (!isFind) {
499             updateInfo.emplace_back(tmpUpdateInfo);
500         }
501     }
502     ifs.close();
503     (void)unlink(MODULE_RESULT_PATH);
504     return updateInfo;
505 }
506 
ProcessSaStatus(const SaStatus & status,std::unordered_set<std::string> & hmpSet)507 void ModuleUpdateService::ProcessSaStatus(const SaStatus &status, std::unordered_set<std::string> &hmpSet)
508 {
509     if (saIdHmpMap_.find(status.saId) == saIdHmpMap_.end()) {
510         return;
511     }
512     std::string hmpName = saIdHmpMap_.at(status.saId);
513     hmpSet.emplace(hmpName);
514     if (!status.isMountSuccess) {
515         OnHmpError(hmpName);
516     }
517 }
518 
OnStart()519 void ModuleUpdateService::OnStart()
520 {
521     LOG(INFO) << "OnStart";
522 }
523 
OnStop()524 void ModuleUpdateService::OnStop()
525 {
526     LOG(INFO) << "OnStop";
527 }
528 
OnProcessCrash(const std::string & processName)529 void ModuleUpdateService::OnProcessCrash(const std::string &processName)
530 {
531     if (processHmpMap_.find(processName) == processHmpMap_.end()) {
532         return;
533     }
534     std::unordered_set<std::string> &hmpSet = processHmpMap_.at(processName);
535     for (auto &hmp : hmpSet) {
536         OnHmpError(hmp);
537     }
538 }
539 
OnBootCompleted()540 void ModuleUpdateService::OnBootCompleted()
541 {
542     LOG(INFO) << "Deleting " << UPDATE_INSTALL_DIR;
543     if (!ForceRemoveDirectory(UPDATE_INSTALL_DIR)) {
544         LOG(ERROR) << "Failed to remove " << UPDATE_INSTALL_DIR << " err=" << errno;
545     }
546     ExitModuleUpdate();
547 }
548 
OnHmpError(const std::string & hmpName)549 void ModuleUpdateService::OnHmpError(const std::string &hmpName)
550 {
551     LOG(INFO) << "OnHmpError hmpName=" << hmpName;
552     std::string activePath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
553     if (!CheckPathExists(activePath)) {
554         LOG(INFO) << "No update package in " << hmpName;
555         return;
556     }
557     std::string errPath = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
558     if (CheckPathExists(errPath) && !ForceRemoveDirectory(errPath)) {
559         LOG(ERROR) << "Failed to remove " << errPath;
560         return;
561     }
562     RevertAndReboot();
563 }
564 
BackupActiveModules() const565 bool ModuleUpdateService::BackupActiveModules() const
566 {
567     if (!CheckPathExists(UPDATE_ACTIVE_DIR)) {
568         LOG(INFO) << "Nothing to backup";
569         return true;
570     }
571     if (CheckPathExists(UPDATE_BACKUP_DIR)) {
572         if (!ForceRemoveDirectory(UPDATE_BACKUP_DIR)) {
573             LOG(ERROR) << "Failed to remove backup dir";
574             return false;
575         }
576     }
577     if (!CreateDirIfNeeded(UPDATE_BACKUP_DIR, DIR_MODE)) {
578         LOG(ERROR) << "Failed to create backup dir";
579         return false;
580     }
581 
582     std::vector<std::string> activeFiles;
583     GetDirFiles(UPDATE_ACTIVE_DIR, activeFiles);
584     ON_SCOPE_EXIT(rmdir) {
585         if (!ForceRemoveDirectory(UPDATE_BACKUP_DIR)) {
586             LOG(WARNING) << "Failed to remove backup dir when backup failed";
587         }
588     };
589     for (const auto &file : activeFiles) {
590         if (!BackupFile(file)) {
591             return false;
592         }
593     }
594 
595     CANCEL_SCOPE_EXIT_GUARD(rmdir);
596     return true;
597 }
598 
RevertAndReboot() const599 bool ModuleUpdateService::RevertAndReboot() const
600 {
601     LOG(INFO) << "RevertAndReboot";
602     if (!CheckPathExists(UPDATE_BACKUP_DIR)) {
603         LOG(ERROR) << UPDATE_BACKUP_DIR << " does not exist";
604         return false;
605     }
606     struct stat statData;
607     int ret = stat(UPDATE_ACTIVE_DIR, &statData);
608     if (ret != 0) {
609         LOG(ERROR) << "Failed to access " << UPDATE_ACTIVE_DIR << " err=" << errno;
610         return false;
611     }
612     if (!ForceRemoveDirectory(UPDATE_ACTIVE_DIR)) {
613         LOG(ERROR) << "Failed to remove " << UPDATE_ACTIVE_DIR;
614         return false;
615     }
616 
617     ret = rename(UPDATE_BACKUP_DIR, UPDATE_ACTIVE_DIR);
618     if (ret != 0) {
619         LOG(ERROR) << "Failed to rename " << UPDATE_BACKUP_DIR << " to " << UPDATE_ACTIVE_DIR << " err=" << errno;
620         return false;
621     }
622     ret = chmod(UPDATE_ACTIVE_DIR, statData.st_mode & ALL_PERMISSIONS);
623     if (ret != 0) {
624         LOG(ERROR) << "Failed to restore original permissions for " << UPDATE_ACTIVE_DIR << " err=" << errno;
625         return false;
626     }
627 
628     sync();
629     LOG(INFO) << "Rebooting";
630     DoReboot("");
631     return true;
632 }
633 
ScanPreInstalledHmp()634 void ModuleUpdateService::ScanPreInstalledHmp()
635 {
636     std::vector<std::string> files;
637     GetDirFiles(MODULE_PREINSTALL_DIR, files);
638     for (auto &file : files) {
639         if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
640             continue;
641         }
642         std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
643         if (moduleFile == nullptr) {
644             continue;
645         }
646         std::string hmpName = GetHmpName(file);
647         if (hmpName.empty()) {
648             continue;
649         }
650         hmpSet_.emplace(hmpName);
651         saIdHmpMap_.emplace(moduleFile->GetSaId(), hmpName);
652     }
653 }
654 } // namespace SysInstaller
655 } // namespace OHOS
656