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