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