188edb362Sopenharmony_ci/* 288edb362Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 388edb362Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 488edb362Sopenharmony_ci * you may not use this file except in compliance with the License. 588edb362Sopenharmony_ci * You may obtain a copy of the License at 688edb362Sopenharmony_ci * 788edb362Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 888edb362Sopenharmony_ci * 988edb362Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1088edb362Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1188edb362Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1288edb362Sopenharmony_ci * See the License for the specific language governing permissions and 1388edb362Sopenharmony_ci * limitations under the License. 1488edb362Sopenharmony_ci */ 1588edb362Sopenharmony_ci 1688edb362Sopenharmony_ci#include "module_update.h" 1788edb362Sopenharmony_ci 1888edb362Sopenharmony_ci#include <chrono> 1988edb362Sopenharmony_ci#include <sys/mount.h> 2088edb362Sopenharmony_ci#include <sys/stat.h> 2188edb362Sopenharmony_ci#include <sys/types.h> 2288edb362Sopenharmony_ci#include <thread> 2388edb362Sopenharmony_ci 2488edb362Sopenharmony_ci#include "directory_ex.h" 2588edb362Sopenharmony_ci#include "log/log.h" 2688edb362Sopenharmony_ci#include "module_constants.h" 2788edb362Sopenharmony_ci#include "module_dm.h" 2888edb362Sopenharmony_ci#include "module_error_code.h" 2988edb362Sopenharmony_ci#include "module_file_repository.h" 3088edb362Sopenharmony_ci#include "module_loop.h" 3188edb362Sopenharmony_ci#include "module_update_task.h" 3288edb362Sopenharmony_ci#include "module_utils.h" 3388edb362Sopenharmony_ci#include "parse_util.h" 3488edb362Sopenharmony_ci#include "scope_guard.h" 3588edb362Sopenharmony_ci#include "string_ex.h" 3688edb362Sopenharmony_ci#include "utils.h" 3788edb362Sopenharmony_ci 3888edb362Sopenharmony_cinamespace OHOS { 3988edb362Sopenharmony_cinamespace SysInstaller { 4088edb362Sopenharmony_ciusing namespace Updater; 4188edb362Sopenharmony_ciusing std::string; 4288edb362Sopenharmony_ci 4388edb362Sopenharmony_cinamespace { 4488edb362Sopenharmony_ciconstexpr mode_t MOUNT_POINT_MODE = 0755; 4588edb362Sopenharmony_ciconstexpr int32_t LOOP_DEVICE_SETUP_ATTEMPTS = 3; 4688edb362Sopenharmony_ci 4788edb362Sopenharmony_cibool CreateLoopDevice(const string &path, const ImageStat &imageStat, Loop::LoopbackDeviceUniqueFd &loopbackDevice) 4888edb362Sopenharmony_ci{ 4988edb362Sopenharmony_ci for (int32_t attempts = 1; attempts <= LOOP_DEVICE_SETUP_ATTEMPTS; ++attempts) { 5088edb362Sopenharmony_ci std::unique_ptr<Loop::LoopbackDeviceUniqueFd> device = 5188edb362Sopenharmony_ci Loop::CreateLoopDevice(path, imageStat.imageOffset, imageStat.imageSize); 5288edb362Sopenharmony_ci if (device != nullptr) { 5388edb362Sopenharmony_ci loopbackDevice = std::move(*device); 5488edb362Sopenharmony_ci break; 5588edb362Sopenharmony_ci } 5688edb362Sopenharmony_ci } 5788edb362Sopenharmony_ci return loopbackDevice.deviceFd.Get() != -1; 5888edb362Sopenharmony_ci} 5988edb362Sopenharmony_ci 6088edb362Sopenharmony_cibool StageUpdateModulePackage(const string &updatePath, const string &stagePath) 6188edb362Sopenharmony_ci{ 6288edb362Sopenharmony_ci int ret = 0; 6388edb362Sopenharmony_ci if (CheckPathExists(stagePath)) { 6488edb362Sopenharmony_ci LOG(INFO) << stagePath << " already exists. Deleting"; 6588edb362Sopenharmony_ci ret = unlink(stagePath.c_str()); 6688edb362Sopenharmony_ci if (ret != 0) { 6788edb362Sopenharmony_ci LOG(ERROR) << "Failed to unlink " << stagePath; 6888edb362Sopenharmony_ci return false; 6988edb362Sopenharmony_ci } 7088edb362Sopenharmony_ci } 7188edb362Sopenharmony_ci string path = ExtractFilePath(stagePath); 7288edb362Sopenharmony_ci // active dir should create by module_update_sa 7388edb362Sopenharmony_ci if (!CheckPathExists(path)) { 7488edb362Sopenharmony_ci LOG(ERROR) << path << " doesn't exist."; 7588edb362Sopenharmony_ci return false; 7688edb362Sopenharmony_ci } 7788edb362Sopenharmony_ci ret = link(updatePath.c_str(), stagePath.c_str()); 7888edb362Sopenharmony_ci if (ret != 0) { 7988edb362Sopenharmony_ci LOG(ERROR) << "Unable to link " << updatePath << " to " << stagePath; 8088edb362Sopenharmony_ci return false; 8188edb362Sopenharmony_ci } 8288edb362Sopenharmony_ci 8388edb362Sopenharmony_ci // stage other files 8488edb362Sopenharmony_ci std::vector<std::string> files; 8588edb362Sopenharmony_ci if (Updater::Utils::GetFilesFromDirectory(updatePath.substr(0, updatePath.rfind("/")), files, true) <= 0) { 8688edb362Sopenharmony_ci LOG(ERROR) << "Failed to get files form " << updatePath; 8788edb362Sopenharmony_ci return false; 8888edb362Sopenharmony_ci } 8988edb362Sopenharmony_ci for (const auto &file : files) { 9088edb362Sopenharmony_ci std::string targetFile = path + ExtractFileName(file); 9188edb362Sopenharmony_ci (void)unlink(targetFile.c_str()); 9288edb362Sopenharmony_ci ret = link(file.c_str(), targetFile.c_str()); 9388edb362Sopenharmony_ci if (ret != 0) { 9488edb362Sopenharmony_ci LOG(ERROR) << "Unable to link " << file << " to " << targetFile; 9588edb362Sopenharmony_ci return false; 9688edb362Sopenharmony_ci } 9788edb362Sopenharmony_ci } 9888edb362Sopenharmony_ci LOG(INFO) << "success to link " << updatePath << " to " << stagePath; 9988edb362Sopenharmony_ci return true; 10088edb362Sopenharmony_ci} 10188edb362Sopenharmony_ci 10288edb362Sopenharmony_cibool CheckModulePackage(const std::string &mountPoint, const ModuleFile &moduleFile) 10388edb362Sopenharmony_ci{ 10488edb362Sopenharmony_ci if (!IsEmptyFolder(mountPoint)) { 10588edb362Sopenharmony_ci LOG(ERROR) << mountPoint << " is not empty"; 10688edb362Sopenharmony_ci return false; 10788edb362Sopenharmony_ci } 10888edb362Sopenharmony_ci if (!moduleFile.GetImageStat().has_value()) { 10988edb362Sopenharmony_ci LOG(ERROR) << "Could not mount empty module package " << moduleFile.GetPath(); 11088edb362Sopenharmony_ci return false; 11188edb362Sopenharmony_ci } 11288edb362Sopenharmony_ci return true; 11388edb362Sopenharmony_ci} 11488edb362Sopenharmony_ci} 11588edb362Sopenharmony_ci 11688edb362Sopenharmony_ciModuleUpdate &ModuleUpdate::GetInstance() 11788edb362Sopenharmony_ci{ 11888edb362Sopenharmony_ci static ModuleUpdate instance; 11988edb362Sopenharmony_ci return instance; 12088edb362Sopenharmony_ci} 12188edb362Sopenharmony_ci 12288edb362Sopenharmony_cibool ModuleUpdate::RemoveMountPoint(const string &hmpName) 12388edb362Sopenharmony_ci{ 12488edb362Sopenharmony_ci string mountPoint = string(MODULE_ROOT_DIR) + "/" + hmpName; 12588edb362Sopenharmony_ci LOG(INFO) << "Remove old mountpoint " << mountPoint; 12688edb362Sopenharmony_ci if (!CheckPathExists(mountPoint)) { 12788edb362Sopenharmony_ci LOG(INFO) << mountPoint << " doesn't exist."; 12888edb362Sopenharmony_ci return true; 12988edb362Sopenharmony_ci } 13088edb362Sopenharmony_ci 13188edb362Sopenharmony_ci std::string prefixes[] = {MODULE_PREINSTALL_DIR, UPDATE_ACTIVE_DIR}; 13288edb362Sopenharmony_ci int ret = -1; 13388edb362Sopenharmony_ci for (auto prefix : prefixes) { 13488edb362Sopenharmony_ci std::string imagePath = prefix + "/" + hmpName + "/" + IMG_FILE_NAME; 13588edb362Sopenharmony_ci if (Loop::RemoveDmLoopDevice(mountPoint, imagePath)) { 13688edb362Sopenharmony_ci ret = 0; 13788edb362Sopenharmony_ci LOG(INFO) << "Successful remove dm loop device, mountPoint=" << mountPoint 13888edb362Sopenharmony_ci << ", imagePath=" << imagePath; 13988edb362Sopenharmony_ci break; 14088edb362Sopenharmony_ci } 14188edb362Sopenharmony_ci } 14288edb362Sopenharmony_ci if (ret != 0) { 14388edb362Sopenharmony_ci LOG(ERROR) << "Fail remove dm loop device, mountPoint=" << mountPoint; 14488edb362Sopenharmony_ci return false; 14588edb362Sopenharmony_ci } 14688edb362Sopenharmony_ci ret = rmdir(mountPoint.c_str()); 14788edb362Sopenharmony_ci if (ret != 0) { 14888edb362Sopenharmony_ci LOG(WARNING) << "Could not rmdir " << mountPoint << " errno: " << errno; 14988edb362Sopenharmony_ci return false; 15088edb362Sopenharmony_ci } 15188edb362Sopenharmony_ci LOG(INFO) << "Successful remove mountPoint, hmpName: " << hmpName; 15288edb362Sopenharmony_ci return true; 15388edb362Sopenharmony_ci} 15488edb362Sopenharmony_ci 15588edb362Sopenharmony_cistd::unique_ptr<ModuleFile> ModuleUpdate::GetLatestUpdateModulePackage(const string &hmpName) 15688edb362Sopenharmony_ci{ 15788edb362Sopenharmony_ci std::unique_ptr<ModuleFile> activeModuleFile = repository_.GetModuleFile(UPDATE_ACTIVE_DIR, hmpName); 15888edb362Sopenharmony_ci std::unique_ptr<ModuleFile> updateModuleFile = repository_.GetModuleFile(UPDATE_INSTALL_DIR, hmpName); 15988edb362Sopenharmony_ci std::unique_ptr<ModuleFile> ret = nullptr; 16088edb362Sopenharmony_ci if (updateModuleFile != nullptr) { 16188edb362Sopenharmony_ci if (activeModuleFile == nullptr || ModuleFile::CompareVersion(*updateModuleFile, *activeModuleFile)) { 16288edb362Sopenharmony_ci string updatePath = updateModuleFile->GetPath(); 16388edb362Sopenharmony_ci string activePath = UPDATE_ACTIVE_DIR + 16488edb362Sopenharmony_ci updatePath.substr(strlen(UPDATE_INSTALL_DIR), updatePath.length()); 16588edb362Sopenharmony_ci if (!StageUpdateModulePackage(updatePath, activePath)) { 16688edb362Sopenharmony_ci return ret; 16788edb362Sopenharmony_ci } 16888edb362Sopenharmony_ci updateModuleFile->SetPath(activePath); 16988edb362Sopenharmony_ci ret = std::move(updateModuleFile); 17088edb362Sopenharmony_ci LOG(INFO) << "add updateModuleFile " << updatePath; 17188edb362Sopenharmony_ci } 17288edb362Sopenharmony_ci } 17388edb362Sopenharmony_ci if (ret == nullptr && activeModuleFile != nullptr) { 17488edb362Sopenharmony_ci LOG(INFO) << "add activeModuleFile " << activeModuleFile->GetPath(); 17588edb362Sopenharmony_ci ret = std::move(activeModuleFile); 17688edb362Sopenharmony_ci } 17788edb362Sopenharmony_ci return ret; 17888edb362Sopenharmony_ci} 17988edb362Sopenharmony_ci 18088edb362Sopenharmony_cibool ModuleUpdate::CheckMountComplete(const string &hmpName) const 18188edb362Sopenharmony_ci{ 18288edb362Sopenharmony_ci string path = std::string(MODULE_ROOT_DIR) + "/" + hmpName; 18388edb362Sopenharmony_ci return CheckPathExists(path); 18488edb362Sopenharmony_ci} 18588edb362Sopenharmony_ci 18688edb362Sopenharmony_civoid ModuleUpdate::ProcessHmpFile(const string &hmpFile, const ModuleUpdateStatus &status, const Timer &timer) 18788edb362Sopenharmony_ci{ 18888edb362Sopenharmony_ci LOG(INFO) << "process hmp file=" << hmpFile; 18988edb362Sopenharmony_ci std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(hmpFile); 19088edb362Sopenharmony_ci if (moduleFile == nullptr) { 19188edb362Sopenharmony_ci LOG(ERROR) << "Process hmp file fail, module file is null"; 19288edb362Sopenharmony_ci return; 19388edb362Sopenharmony_ci } 19488edb362Sopenharmony_ci HmpInstallType type = moduleFile->GetHmpPackageType(); 19588edb362Sopenharmony_ci if (CheckBootComplete() && IsHotHmpPackage(static_cast<int32_t>(type))) { 19688edb362Sopenharmony_ci if (type == HOT_SA_TYPE && IsRunning(moduleFile->GetVersionInfo().saInfoList.front().saId)) { 19788edb362Sopenharmony_ci LOG(INFO) << "ondemand sa is running, saId=" << moduleFile->GetVersionInfo().saInfoList.front().saId; 19888edb362Sopenharmony_ci return; 19988edb362Sopenharmony_ci } 20088edb362Sopenharmony_ci if (type == HOT_APP_TYPE) { 20188edb362Sopenharmony_ci KillProcessOnArkWeb(); 20288edb362Sopenharmony_ci } 20388edb362Sopenharmony_ci if (!RemoveMountPoint(status.hmpName)) { 20488edb362Sopenharmony_ci return; 20588edb362Sopenharmony_ci } 20688edb362Sopenharmony_ci } else if (CheckMountComplete(status.hmpName)) { 20788edb362Sopenharmony_ci LOG(INFO) << "Check mount complete, hmpName=" << status.hmpName; 20888edb362Sopenharmony_ci return; 20988edb362Sopenharmony_ci } 21088edb362Sopenharmony_ci repository_.InitRepository(status.hmpName, timer); 21188edb362Sopenharmony_ci PrepareModuleFileList(status); 21288edb362Sopenharmony_ci} 21388edb362Sopenharmony_ci 21488edb362Sopenharmony_cibool ModuleUpdate::DoModuleUpdate(ModuleUpdateStatus &status) 21588edb362Sopenharmony_ci{ 21688edb362Sopenharmony_ci LOG(INFO) << "enter domoduleupdate"; 21788edb362Sopenharmony_ci Timer timer; 21888edb362Sopenharmony_ci std::string hmpPackagePath = std::string(MODULE_PREINSTALL_DIR) + "/" + status.hmpName; 21988edb362Sopenharmony_ci LOG(INFO) << "DoModuleUpdate hmp package path=" << hmpPackagePath; 22088edb362Sopenharmony_ci std::vector<std::string> files; 22188edb362Sopenharmony_ci GetDirFiles(hmpPackagePath, files); 22288edb362Sopenharmony_ci ON_SCOPE_EXIT(clear) { 22388edb362Sopenharmony_ci repository_.Clear(); 22488edb362Sopenharmony_ci moduleFileList_.clear(); 22588edb362Sopenharmony_ci }; 22688edb362Sopenharmony_ci for (auto &file : files) { 22788edb362Sopenharmony_ci std::string hmpPackage = GetFileName(file); 22888edb362Sopenharmony_ci if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX) || hmpPackage.empty()) { 22988edb362Sopenharmony_ci continue; 23088edb362Sopenharmony_ci } 23188edb362Sopenharmony_ci ProcessHmpFile(file, status, timer); 23288edb362Sopenharmony_ci } 23388edb362Sopenharmony_ci if (moduleFileList_.size() != 1) { 23488edb362Sopenharmony_ci LOG(INFO) << status.hmpName << " module size is invalid: " << moduleFileList_.size(); 23588edb362Sopenharmony_ci return false; 23688edb362Sopenharmony_ci } 23788edb362Sopenharmony_ci if (!Loop::PreAllocateLoopDevices(moduleFileList_.size())) { 23888edb362Sopenharmony_ci LOG(ERROR) << "Failed to pre allocate loop devices, hmp package name=" << status.hmpName; 23988edb362Sopenharmony_ci return false; 24088edb362Sopenharmony_ci } 24188edb362Sopenharmony_ci if (!ActivateModules(status, timer)) { 24288edb362Sopenharmony_ci LOG(ERROR) << "Failed to activate modules, hmp package name=" << status.hmpName; 24388edb362Sopenharmony_ci return false; 24488edb362Sopenharmony_ci } 24588edb362Sopenharmony_ci LOG(INFO) << "Success to activate modules, hmp package name=" << status.hmpName; 24688edb362Sopenharmony_ci return true; 24788edb362Sopenharmony_ci} 24888edb362Sopenharmony_ci 24988edb362Sopenharmony_civoid ModuleUpdate::CheckModuleUpdate() 25088edb362Sopenharmony_ci{ 25188edb362Sopenharmony_ci LOG(INFO) << "CheckModuleUpdate begin"; 25288edb362Sopenharmony_ci Timer timer; 25388edb362Sopenharmony_ci std::vector<std::string> files; 25488edb362Sopenharmony_ci std::unordered_set<std::string> hmpNameSet; 25588edb362Sopenharmony_ci GetDirFiles(MODULE_PREINSTALL_DIR, files); 25688edb362Sopenharmony_ci for (auto &file : files) { 25788edb362Sopenharmony_ci if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) { 25888edb362Sopenharmony_ci continue; 25988edb362Sopenharmony_ci } 26088edb362Sopenharmony_ci std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file); 26188edb362Sopenharmony_ci if (moduleFile == nullptr) { 26288edb362Sopenharmony_ci continue; 26388edb362Sopenharmony_ci } 26488edb362Sopenharmony_ci std::string hmpName = GetHmpName(file); 26588edb362Sopenharmony_ci if (hmpName.empty()) { 26688edb362Sopenharmony_ci continue; 26788edb362Sopenharmony_ci } 26888edb362Sopenharmony_ci hmpNameSet.emplace(hmpName); 26988edb362Sopenharmony_ci } 27088edb362Sopenharmony_ci auto &instance = ModuleUpdateTaskManager::GetInstance(); 27188edb362Sopenharmony_ci instance.Start(); 27288edb362Sopenharmony_ci ON_SCOPE_EXIT(clear) { 27388edb362Sopenharmony_ci instance.ClearTask(); 27488edb362Sopenharmony_ci instance.Stop(); 27588edb362Sopenharmony_ci LOG(INFO) << "CheckModuleUpdate done, duration=" << timer; 27688edb362Sopenharmony_ci if (!ForceRemoveDirectory(UPDATE_INSTALL_DIR)) { 27788edb362Sopenharmony_ci LOG(ERROR) << "Failed to remove " << UPDATE_INSTALL_DIR << " err=" << errno; 27888edb362Sopenharmony_ci } 27988edb362Sopenharmony_ci }; 28088edb362Sopenharmony_ci for (auto &hmpName : hmpNameSet) { 28188edb362Sopenharmony_ci instance.AddTask(hmpName); 28288edb362Sopenharmony_ci } 28388edb362Sopenharmony_ci while (instance.GetCurTaskNum() != 0) { 28488edb362Sopenharmony_ci sleep(1); 28588edb362Sopenharmony_ci } 28688edb362Sopenharmony_ci} 28788edb362Sopenharmony_ci 28888edb362Sopenharmony_civoid ModuleUpdate::PrepareModuleFileList(const ModuleUpdateStatus &status) 28988edb362Sopenharmony_ci{ 29088edb362Sopenharmony_ci std::unique_ptr<ModuleFile> systemModuleFile = repository_.GetModuleFile(MODULE_PREINSTALL_DIR, status.hmpName); 29188edb362Sopenharmony_ci if (systemModuleFile == nullptr) { 29288edb362Sopenharmony_ci LOG(ERROR) << "Failed to get preinstalled hmp " << status.hmpName; 29388edb362Sopenharmony_ci return; 29488edb362Sopenharmony_ci } 29588edb362Sopenharmony_ci std::unique_ptr<ModuleFile> latestModuleFile = GetLatestUpdateModulePackage(status.hmpName); 29688edb362Sopenharmony_ci if (latestModuleFile != nullptr && ModuleFile::CompareVersion(*latestModuleFile, *systemModuleFile)) { 29788edb362Sopenharmony_ci moduleFileList_.emplace_back(std::move(*latestModuleFile)); 29888edb362Sopenharmony_ci } else { 29988edb362Sopenharmony_ci moduleFileList_.emplace_back(std::move(*systemModuleFile)); 30088edb362Sopenharmony_ci // when choose preInstall hmp, remove activeHmp and backupHmp 30188edb362Sopenharmony_ci RemoveSpecifiedDir(std::string(UPDATE_ACTIVE_DIR) + "/" + status.hmpName); 30288edb362Sopenharmony_ci RemoveSpecifiedDir(std::string(UPDATE_BACKUP_DIR) + "/" + status.hmpName); 30388edb362Sopenharmony_ci } 30488edb362Sopenharmony_ci} 30588edb362Sopenharmony_ci 30688edb362Sopenharmony_cibool ModuleUpdate::ActivateModules(ModuleUpdateStatus &status, const Timer &timer) 30788edb362Sopenharmony_ci{ 30888edb362Sopenharmony_ci // size = 1 30988edb362Sopenharmony_ci for (const auto &moduleFile : moduleFileList_) { 31088edb362Sopenharmony_ci if (!moduleFile.GetImageStat().has_value()) { 31188edb362Sopenharmony_ci LOG(INFO) << moduleFile.GetPath() << " is empty module package"; 31288edb362Sopenharmony_ci continue; 31388edb362Sopenharmony_ci } 31488edb362Sopenharmony_ci status.isPreInstalled = repository_.IsPreInstalledModule(moduleFile); 31588edb362Sopenharmony_ci status.isHotInstall = IsHotHmpPackage(static_cast<int32_t>(moduleFile.GetHmpPackageType())); 31688edb362Sopenharmony_ci status.isAllMountSuccess = MountModulePackage(moduleFile, !status.isPreInstalled); 31788edb362Sopenharmony_ci if (!status.isAllMountSuccess) { 31888edb362Sopenharmony_ci LOG(ERROR) << "Failed to mount module package " << moduleFile.GetPath(); 31988edb362Sopenharmony_ci repository_.SaveInstallerResult(moduleFile.GetPath(), status.hmpName, 32088edb362Sopenharmony_ci ERR_INSTALL_FAIL, "mount fail", timer); 32188edb362Sopenharmony_ci } 32288edb362Sopenharmony_ci // bugfix: when sise = 1, for() find the second item 32388edb362Sopenharmony_ci break; 32488edb362Sopenharmony_ci } 32588edb362Sopenharmony_ci ReportModuleUpdateStatus(status); 32688edb362Sopenharmony_ci LOG(INFO) << "ActivateModule mount result:" << status.isAllMountSuccess << ", hmp package name:" << status.hmpName; 32788edb362Sopenharmony_ci return status.isAllMountSuccess; 32888edb362Sopenharmony_ci} 32988edb362Sopenharmony_ci 33088edb362Sopenharmony_civoid ModuleUpdate::WaitDevice(const std::string &blockDevice) const 33188edb362Sopenharmony_ci{ 33288edb362Sopenharmony_ci const int waitTime = 150; // wait max 3s 33388edb362Sopenharmony_ci int time = 0; 33488edb362Sopenharmony_ci while (!CheckPathExists(blockDevice) && time++ < waitTime) { 33588edb362Sopenharmony_ci usleep(20000); // 20000: 20ms 33688edb362Sopenharmony_ci } 33788edb362Sopenharmony_ci} 33888edb362Sopenharmony_ci 33988edb362Sopenharmony_cibool ModuleUpdate::MountModulePackage(const ModuleFile &moduleFile, const bool mountOnVerity) const 34088edb362Sopenharmony_ci{ 34188edb362Sopenharmony_ci string mountPoint = string(MODULE_ROOT_DIR) + "/" + moduleFile.GetVersionInfo().hmpName; 34288edb362Sopenharmony_ci LOG(INFO) << "Creating mount point: " << mountPoint; 34388edb362Sopenharmony_ci Timer timer; 34488edb362Sopenharmony_ci int ret = 0; 34588edb362Sopenharmony_ci if (!CreateDirIfNeeded(mountPoint, MOUNT_POINT_MODE)) { 34688edb362Sopenharmony_ci LOG(ERROR) << "Could not create mount point " << mountPoint << " errno: " << errno; 34788edb362Sopenharmony_ci return false; 34888edb362Sopenharmony_ci } 34988edb362Sopenharmony_ci ON_SCOPE_EXIT(rmDir) { 35088edb362Sopenharmony_ci ret = rmdir(mountPoint.c_str()); 35188edb362Sopenharmony_ci if (ret != 0) { 35288edb362Sopenharmony_ci LOG(WARNING) << "Could not rmdir " << mountPoint << " errno: " << errno; 35388edb362Sopenharmony_ci } 35488edb362Sopenharmony_ci }; 35588edb362Sopenharmony_ci if (!CheckModulePackage(mountPoint, moduleFile)) { 35688edb362Sopenharmony_ci return false; 35788edb362Sopenharmony_ci } 35888edb362Sopenharmony_ci 35988edb362Sopenharmony_ci const string &fullPath = ExtractFilePath(moduleFile.GetPath()) + IMG_FILE_NAME; 36088edb362Sopenharmony_ci const ImageStat &imageStat = moduleFile.GetImageStat().value(); 36188edb362Sopenharmony_ci Loop::LoopbackDeviceUniqueFd loopbackDevice; 36288edb362Sopenharmony_ci if (!CreateLoopDevice(fullPath, imageStat, loopbackDevice)) { 36388edb362Sopenharmony_ci LOG(ERROR) << "Could not create loop device for " << fullPath; 36488edb362Sopenharmony_ci return false; 36588edb362Sopenharmony_ci } 36688edb362Sopenharmony_ci LOG(INFO) << "Loopback device created: " << loopbackDevice.name << " fsType=" << imageStat.fsType; 36788edb362Sopenharmony_ci string blockDevice = loopbackDevice.name; 36888edb362Sopenharmony_ci if (mountOnVerity) { 36988edb362Sopenharmony_ci if (!CreateDmDevice(moduleFile, blockDevice)) { 37088edb362Sopenharmony_ci LOG(ERROR) << "Could not create dm-verity device on " << blockDevice; 37188edb362Sopenharmony_ci Loop::ClearDmLoopDevice(blockDevice, false); 37288edb362Sopenharmony_ci return false; 37388edb362Sopenharmony_ci } 37488edb362Sopenharmony_ci } 37588edb362Sopenharmony_ci WaitDevice(blockDevice); 37688edb362Sopenharmony_ci uint32_t mountFlags = MS_NOATIME | MS_NODEV | MS_DIRSYNC | MS_RDONLY; 37788edb362Sopenharmony_ci ret = mount(blockDevice.c_str(), mountPoint.c_str(), imageStat.fsType, mountFlags, nullptr); 37888edb362Sopenharmony_ci if (ret != 0) { 37988edb362Sopenharmony_ci LOG(ERROR) << "Mounting failed for module package " << fullPath << " errno:" << errno; 38088edb362Sopenharmony_ci Loop::ClearDmLoopDevice(blockDevice, true); 38188edb362Sopenharmony_ci return false; 38288edb362Sopenharmony_ci } 38388edb362Sopenharmony_ci LOG(INFO) << "Successfully mounted module package " << fullPath << " on " << mountPoint << " duration=" << timer; 38488edb362Sopenharmony_ci loopbackDevice.CloseGood(); 38588edb362Sopenharmony_ci CANCEL_SCOPE_EXIT_GUARD(rmDir); 38688edb362Sopenharmony_ci return true; 38788edb362Sopenharmony_ci} 38888edb362Sopenharmony_ci 38988edb362Sopenharmony_civoid ModuleUpdate::ReportModuleUpdateStatus(const ModuleUpdateStatus &status) const 39088edb362Sopenharmony_ci{ 39188edb362Sopenharmony_ci auto &instance = ModuleUpdateTaskManager::GetInstance(); 39288edb362Sopenharmony_ci if (!instance.GetTaskResult()) { 39388edb362Sopenharmony_ci LOG(ERROR) << "ReportModuleUpdateStatus, module update fail"; 39488edb362Sopenharmony_ci instance.ClearTask(); 39588edb362Sopenharmony_ci } 39688edb362Sopenharmony_ci if (!status.isAllMountSuccess) { 39788edb362Sopenharmony_ci LOG(ERROR) << "ReportModuleUpdateStatus mount fail, hmp name=" << status.hmpName; 39888edb362Sopenharmony_ci RemoveSpecifiedDir(std::string(UPDATE_INSTALL_DIR) + "/" + status.hmpName); 39988edb362Sopenharmony_ci Revert(status.hmpName, !status.isHotInstall); 40088edb362Sopenharmony_ci return; 40188edb362Sopenharmony_ci } 40288edb362Sopenharmony_ci LOG(INFO) << "ReportModuleUpdateStatus mount success, hmp name=" << status.hmpName; 40388edb362Sopenharmony_ci} 40488edb362Sopenharmony_ci} // namespace SysInstaller 40588edb362Sopenharmony_ci} // namespace OHOS 406