1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci#include "include/updater/updater.h"
16fb299fa2Sopenharmony_ci#include <cerrno>
17fb299fa2Sopenharmony_ci#include <chrono>
18fb299fa2Sopenharmony_ci#include <cstdio>
19fb299fa2Sopenharmony_ci#include <iomanip>
20fb299fa2Sopenharmony_ci#include <string>
21fb299fa2Sopenharmony_ci#include <sched.h>
22fb299fa2Sopenharmony_ci#include <syscall.h>
23fb299fa2Sopenharmony_ci#include <sys/stat.h>
24fb299fa2Sopenharmony_ci#include <sys/statvfs.h>
25fb299fa2Sopenharmony_ci#include <sys/wait.h>
26fb299fa2Sopenharmony_ci#include <thread>
27fb299fa2Sopenharmony_ci#include <unistd.h>
28fb299fa2Sopenharmony_ci#include <vector>
29fb299fa2Sopenharmony_ci#include <algorithm>
30fb299fa2Sopenharmony_ci#include "fs_manager/mount.h"
31fb299fa2Sopenharmony_ci#include "language/language_ui.h"
32fb299fa2Sopenharmony_ci#include "log/dump.h"
33fb299fa2Sopenharmony_ci#include "log/log.h"
34fb299fa2Sopenharmony_ci#include "package/hash_data_verifier.h"
35fb299fa2Sopenharmony_ci#include "package/pkg_manager.h"
36fb299fa2Sopenharmony_ci#include "package/packages_info.h"
37fb299fa2Sopenharmony_ci#include "parameter.h"
38fb299fa2Sopenharmony_ci#include "misc_info/misc_info.h"
39fb299fa2Sopenharmony_ci#ifdef WITH_SELINUX
40fb299fa2Sopenharmony_ci#include <policycoreutils.h>
41fb299fa2Sopenharmony_ci#include "selinux/selinux.h"
42fb299fa2Sopenharmony_ci#endif // WITH_SELINUX
43fb299fa2Sopenharmony_ci#ifdef UPDATER_USE_PTABLE
44fb299fa2Sopenharmony_ci#include "ptable_parse/ptable_manager.h"
45fb299fa2Sopenharmony_ci#endif
46fb299fa2Sopenharmony_ci#include "updater/hwfault_retry.h"
47fb299fa2Sopenharmony_ci#include "updater/updater_preprocess.h"
48fb299fa2Sopenharmony_ci#include "updater/updater_const.h"
49fb299fa2Sopenharmony_ci#include "updater_main.h"
50fb299fa2Sopenharmony_ci#include "updater_ui_stub.h"
51fb299fa2Sopenharmony_ci#include "utils.h"
52fb299fa2Sopenharmony_ci#include "write_state/write_state.h"
53fb299fa2Sopenharmony_ci
54fb299fa2Sopenharmony_cinamespace Updater {
55fb299fa2Sopenharmony_ciusing Updater::Utils::SplitString;
56fb299fa2Sopenharmony_ciusing Updater::Utils::Trim;
57fb299fa2Sopenharmony_ciusing namespace Hpackage;
58fb299fa2Sopenharmony_ci
59fb299fa2Sopenharmony_ciint g_percentage = 100;
60fb299fa2Sopenharmony_ciint g_tmpProgressValue;
61fb299fa2Sopenharmony_ciint g_tmpValue;
62fb299fa2Sopenharmony_ci
63fb299fa2Sopenharmony_ciint32_t ExtractUpdaterBinary(PkgManager::PkgManagerPtr manager, std::string &packagePath,
64fb299fa2Sopenharmony_ci    const std::string &updaterBinary)
65fb299fa2Sopenharmony_ci{
66fb299fa2Sopenharmony_ci    PkgManager::StreamPtr outStream = nullptr;
67fb299fa2Sopenharmony_ci    int32_t ret = manager->CreatePkgStream(outStream,  GetWorkPath() + updaterBinary,
68fb299fa2Sopenharmony_ci        0, PkgStream::PkgStreamType_Write);
69fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
70fb299fa2Sopenharmony_ci        LOG(ERROR) << "ExtractUpdaterBinary create stream fail";
71fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_CORRUPT);
72fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
73fb299fa2Sopenharmony_ci    }
74fb299fa2Sopenharmony_ci    ret = manager->ExtractFile(updaterBinary, outStream);
75fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
76fb299fa2Sopenharmony_ci        LOG(ERROR) << "ExtractUpdaterBinary extract file failed";
77fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_CORRUPT);
78fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
79fb299fa2Sopenharmony_ci    }
80fb299fa2Sopenharmony_ci    HashDataVerifier verifier {manager};
81fb299fa2Sopenharmony_ci    if (!verifier.LoadHashDataAndPkcs7(packagePath) ||
82fb299fa2Sopenharmony_ci        !verifier.VerifyHashData("build_tools/", updaterBinary, outStream)) {
83fb299fa2Sopenharmony_ci        LOG(ERROR) << "verify updater_binary failed";
84fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_CORRUPT);
85fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
86fb299fa2Sopenharmony_ci    }
87fb299fa2Sopenharmony_ci    manager->ClosePkgStream(outStream);
88fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
89fb299fa2Sopenharmony_ci}
90fb299fa2Sopenharmony_ci
91fb299fa2Sopenharmony_ciint GetUpdatePackageInfo(PkgManager::PkgManagerPtr pkgManager, const std::string &path)
92fb299fa2Sopenharmony_ci{
93fb299fa2Sopenharmony_ci    std::vector<std::string> components;
94fb299fa2Sopenharmony_ci    if (pkgManager == nullptr) {
95fb299fa2Sopenharmony_ci        LOG(ERROR) << "pkgManager is nullptr";
96fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
97fb299fa2Sopenharmony_ci    }
98fb299fa2Sopenharmony_ci    int32_t ret = pkgManager->LoadPackage(path, Utils::GetCertName(), components);
99fb299fa2Sopenharmony_ci    if (ret != PKG_SUCCESS) {
100fb299fa2Sopenharmony_ci        LOG(INFO) << "LoadPackage fail ret :"<< ret;
101fb299fa2Sopenharmony_ci        return ret;
102fb299fa2Sopenharmony_ci    }
103fb299fa2Sopenharmony_ci    return PKG_SUCCESS;
104fb299fa2Sopenharmony_ci}
105fb299fa2Sopenharmony_ci
106fb299fa2Sopenharmony_ciUpdaterStatus IsSpaceCapacitySufficient(const UpdaterParams &upParams)
107fb299fa2Sopenharmony_ci{
108fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
109fb299fa2Sopenharmony_ci    std::vector<uint64_t> stashSizeList = GetStashSizeList(upParams);
110fb299fa2Sopenharmony_ci    if (stashSizeList.size() == 0) {
111fb299fa2Sopenharmony_ci        LOG(ERROR) << "get stash size error";
112fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
113fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
114fb299fa2Sopenharmony_ci    }
115fb299fa2Sopenharmony_ci    uint64_t maxStashSize =  *max_element(stashSizeList.begin(), stashSizeList.end());
116fb299fa2Sopenharmony_ci    LOG(INFO) << "get max stash size:" << maxStashSize;
117fb299fa2Sopenharmony_ci    uint64_t totalPkgSize = maxStashSize + MIN_UPDATE_SPACE;
118fb299fa2Sopenharmony_ci
119fb299fa2Sopenharmony_ci    if (CheckStatvfs(totalPkgSize) != UPDATE_SUCCESS) {
120fb299fa2Sopenharmony_ci        LOG(ERROR) << "CheckStatvfs error";
121fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
122fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
123fb299fa2Sopenharmony_ci    }
124fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
125fb299fa2Sopenharmony_ci}
126fb299fa2Sopenharmony_ci
127fb299fa2Sopenharmony_cistd::vector<uint64_t> GetStashSizeList(const UpdaterParams &upParams)
128fb299fa2Sopenharmony_ci{
129fb299fa2Sopenharmony_ci    const std::string maxStashFileName = "all_max_stash";
130fb299fa2Sopenharmony_ci    std::vector<uint64_t> stashSizeList;
131fb299fa2Sopenharmony_ci    for (unsigned int i = upParams.pkgLocation; i < upParams.updatePackage.size(); i++) {
132fb299fa2Sopenharmony_ci        PkgManager::PkgManagerPtr pkgManager = Hpackage::PkgManager::CreatePackageInstance();
133fb299fa2Sopenharmony_ci        if (pkgManager == nullptr) {
134fb299fa2Sopenharmony_ci            LOG(ERROR) << "pkgManager is nullptr";
135fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(UPDATE_CORRUPT);
136fb299fa2Sopenharmony_ci            return std::vector<uint64_t> {};
137fb299fa2Sopenharmony_ci        }
138fb299fa2Sopenharmony_ci
139fb299fa2Sopenharmony_ci        std::vector<std::string> fileIds;
140fb299fa2Sopenharmony_ci        int ret = pkgManager->LoadPackageWithoutUnPack(upParams.updatePackage[i], fileIds);
141fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS) {
142fb299fa2Sopenharmony_ci            LOG(ERROR) << "LoadPackageWithoutUnPack failed " << upParams.updatePackage[i];
143fb299fa2Sopenharmony_ci            PkgManager::ReleasePackageInstance(pkgManager);
144fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(UPDATE_CORRUPT);
145fb299fa2Sopenharmony_ci            return  std::vector<uint64_t> {};
146fb299fa2Sopenharmony_ci        }
147fb299fa2Sopenharmony_ci
148fb299fa2Sopenharmony_ci        const FileInfo *info = pkgManager->GetFileInfo(maxStashFileName);
149fb299fa2Sopenharmony_ci        if (info == nullptr) {
150fb299fa2Sopenharmony_ci            LOG(INFO) << "all_max_stash not exist " << upParams.updatePackage[i];
151fb299fa2Sopenharmony_ci            stashSizeList.push_back(0);
152fb299fa2Sopenharmony_ci            PkgManager::ReleasePackageInstance(pkgManager);
153fb299fa2Sopenharmony_ci            continue;
154fb299fa2Sopenharmony_ci        }
155fb299fa2Sopenharmony_ci
156fb299fa2Sopenharmony_ci        PkgManager::StreamPtr outStream = nullptr;
157fb299fa2Sopenharmony_ci        ret = pkgManager->CreatePkgStream(outStream, maxStashFileName, info->unpackedSize,
158fb299fa2Sopenharmony_ci            PkgStream::PkgStreamType_MemoryMap);
159fb299fa2Sopenharmony_ci        if (outStream == nullptr || ret != PKG_SUCCESS) {
160fb299fa2Sopenharmony_ci            LOG(ERROR) << "Create stream fail " << maxStashFileName << " in " << upParams.updatePackage[i];
161fb299fa2Sopenharmony_ci            PkgManager::ReleasePackageInstance(pkgManager);
162fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(UPDATE_CORRUPT);
163fb299fa2Sopenharmony_ci            return std::vector<uint64_t> {};
164fb299fa2Sopenharmony_ci        }
165fb299fa2Sopenharmony_ci
166fb299fa2Sopenharmony_ci        ret = pkgManager->ExtractFile(maxStashFileName, outStream);
167fb299fa2Sopenharmony_ci        if (ret != PKG_SUCCESS) {
168fb299fa2Sopenharmony_ci            LOG(ERROR) << "ExtractFile fail " << maxStashFileName << " in " << upParams.updatePackage[i];
169fb299fa2Sopenharmony_ci            PkgManager::ReleasePackageInstance(pkgManager);
170fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(UPDATE_CORRUPT);
171fb299fa2Sopenharmony_ci            return std::vector<uint64_t> {};
172fb299fa2Sopenharmony_ci        }
173fb299fa2Sopenharmony_ci        PkgBuffer data {};
174fb299fa2Sopenharmony_ci        outStream->GetBuffer(data);
175fb299fa2Sopenharmony_ci        std::string str(reinterpret_cast<char*>(data.buffer), data.length);
176fb299fa2Sopenharmony_ci        int64_t maxStashSize = std::stoll(str);
177fb299fa2Sopenharmony_ci        stashSizeList.push_back(static_cast<uint64_t>(maxStashSize));
178fb299fa2Sopenharmony_ci        PkgManager::ReleasePackageInstance(pkgManager);
179fb299fa2Sopenharmony_ci    }
180fb299fa2Sopenharmony_ci    return stashSizeList;
181fb299fa2Sopenharmony_ci}
182fb299fa2Sopenharmony_ci
183fb299fa2Sopenharmony_ciint CheckStatvfs(const uint64_t totalPkgSize)
184fb299fa2Sopenharmony_ci{
185fb299fa2Sopenharmony_ci    struct statvfs64 updaterVfs;
186fb299fa2Sopenharmony_ci    if (access("/sdcard/updater", 0) == 0) {
187fb299fa2Sopenharmony_ci        if (statvfs64("/sdcard", &updaterVfs) < 0) {
188fb299fa2Sopenharmony_ci            LOG(ERROR) << "Statvfs read /sdcard error!";
189fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(UPDATE_ERROR);
190fb299fa2Sopenharmony_ci            return UPDATE_ERROR;
191fb299fa2Sopenharmony_ci        }
192fb299fa2Sopenharmony_ci    } else {
193fb299fa2Sopenharmony_ci        if (statvfs64("/data", &updaterVfs) < 0) {
194fb299fa2Sopenharmony_ci            LOG(ERROR) << "Statvfs read /data error!";
195fb299fa2Sopenharmony_ci            UPDATER_LAST_WORD(UPDATE_ERROR);
196fb299fa2Sopenharmony_ci            return UPDATE_ERROR;
197fb299fa2Sopenharmony_ci        }
198fb299fa2Sopenharmony_ci    }
199fb299fa2Sopenharmony_ci    LOG(INFO) << "Number of free blocks = " << updaterVfs.f_bfree << ", Number of free inodes = " << updaterVfs.f_ffree;
200fb299fa2Sopenharmony_ci    if (static_cast<uint64_t>(updaterVfs.f_bfree) * static_cast<uint64_t>(updaterVfs.f_bsize) <= totalPkgSize) {
201fb299fa2Sopenharmony_ci        LOG(ERROR) << "Can not update, free space is not enough";
202fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SPACE_NOTENOUGH), true);
203fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.Sleep(UI_SHOW_DURATION);
204fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
205fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
206fb299fa2Sopenharmony_ci    }
207fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
208fb299fa2Sopenharmony_ci}
209fb299fa2Sopenharmony_ci
210fb299fa2Sopenharmony_ciint GetTmpProgressValue()
211fb299fa2Sopenharmony_ci{
212fb299fa2Sopenharmony_ci    return g_tmpProgressValue;
213fb299fa2Sopenharmony_ci}
214fb299fa2Sopenharmony_ci
215fb299fa2Sopenharmony_civoid SetTmpProgressValue(int value)
216fb299fa2Sopenharmony_ci{
217fb299fa2Sopenharmony_ci    g_tmpProgressValue = value;
218fb299fa2Sopenharmony_ci}
219fb299fa2Sopenharmony_ci
220fb299fa2Sopenharmony_civoid ProgressSmoothHandler(int beginProgress, int endProgress)
221fb299fa2Sopenharmony_ci{
222fb299fa2Sopenharmony_ci    if (endProgress < 0 || endProgress > FULL_PERCENT_PROGRESS || beginProgress < 0) {
223fb299fa2Sopenharmony_ci        return;
224fb299fa2Sopenharmony_ci    }
225fb299fa2Sopenharmony_ci    while (beginProgress < endProgress) {
226fb299fa2Sopenharmony_ci        int increase = (endProgress - beginProgress) / PROGRESS_VALUE_CONST;
227fb299fa2Sopenharmony_ci        beginProgress += increase;
228fb299fa2Sopenharmony_ci        if (beginProgress >= endProgress || increase == 0) {
229fb299fa2Sopenharmony_ci            break;
230fb299fa2Sopenharmony_ci        } else {
231fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.ShowProgress(beginProgress);
232fb299fa2Sopenharmony_ci            UPDATER_UI_INSTANCE.Sleep(SHOW_FULL_PROGRESS_TIME);
233fb299fa2Sopenharmony_ci        }
234fb299fa2Sopenharmony_ci    }
235fb299fa2Sopenharmony_ci}
236fb299fa2Sopenharmony_ci
237fb299fa2Sopenharmony_ci__attribute__((weak)) bool PreStartBinaryEntry([[maybe_unused]] const std::string &path)
238fb299fa2Sopenharmony_ci{
239fb299fa2Sopenharmony_ci    LOG(INFO) << "pre binary process";
240fb299fa2Sopenharmony_ci    return true;
241fb299fa2Sopenharmony_ci}
242fb299fa2Sopenharmony_ci
243fb299fa2Sopenharmony_ciUpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams,
244fb299fa2Sopenharmony_ci    PackageUpdateMode updateMode)
245fb299fa2Sopenharmony_ci{
246fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
247fb299fa2Sopenharmony_ci    UPDATER_UI_INSTANCE.ShowProgressPage();
248fb299fa2Sopenharmony_ci    if (upParams.callbackProgress == nullptr) {
249fb299fa2Sopenharmony_ci        LOG(ERROR) << "CallbackProgress is nullptr";
250fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_CORRUPT);
251fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
252fb299fa2Sopenharmony_ci    }
253fb299fa2Sopenharmony_ci    upParams.callbackProgress(upParams.initialProgress * FULL_PERCENT_PROGRESS);
254fb299fa2Sopenharmony_ci    if (pkgManager == nullptr) {
255fb299fa2Sopenharmony_ci        LOG(ERROR) << "pkgManager is nullptr";
256fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_CORRUPT);
257fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
258fb299fa2Sopenharmony_ci    }
259fb299fa2Sopenharmony_ci
260fb299fa2Sopenharmony_ci    if (SetupPartitions(updateMode != SDCARD_UPDATE || upParams.sdExtMode == SDCARD_UPDATE_FROM_DEV ||
261fb299fa2Sopenharmony_ci        upParams.sdExtMode == SDCARD_UPDATE_FROM_DATA || Utils::CheckUpdateMode(Updater::SDCARD_INTRAL_MODE) ||
262fb299fa2Sopenharmony_ci        Utils::CheckUpdateMode(Updater::FACTORY_INTERNAL_MODE)) != 0) {
263fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_SETPART_FAIL), true);
264fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
265fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
266fb299fa2Sopenharmony_ci    }
267fb299fa2Sopenharmony_ci
268fb299fa2Sopenharmony_ci    if (upParams.retryCount > 0) {
269fb299fa2Sopenharmony_ci        LOG(INFO) << "Retry for " << upParams.retryCount << " time(s)";
270fb299fa2Sopenharmony_ci    }
271fb299fa2Sopenharmony_ci    int ret = GetUpdatePackageInfo(pkgManager, upParams.updatePackage[upParams.pkgLocation]);
272fb299fa2Sopenharmony_ci    if (ret != 0) {
273fb299fa2Sopenharmony_ci        LOG(ERROR) << "get update package info fail";
274fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
275fb299fa2Sopenharmony_ci    }
276fb299fa2Sopenharmony_ci    if (!PreStartBinaryEntry(upParams.updatePackage[upParams.pkgLocation])) {
277fb299fa2Sopenharmony_ci        LOG(ERROR) << "pre binary process failed";
278fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
279fb299fa2Sopenharmony_ci    }
280fb299fa2Sopenharmony_ci
281fb299fa2Sopenharmony_ci    g_tmpProgressValue = 0;
282fb299fa2Sopenharmony_ci    UpdaterStatus updateRet = StartUpdaterProc(pkgManager, upParams);
283fb299fa2Sopenharmony_ci    if (updateRet != UPDATE_SUCCESS) {
284fb299fa2Sopenharmony_ci        UPDATER_UI_INSTANCE.ShowUpdInfo(TR(UPD_INSTALL_FAIL));
285fb299fa2Sopenharmony_ci        LOG(ERROR) << "Install package failed.";
286fb299fa2Sopenharmony_ci    }
287fb299fa2Sopenharmony_ci    if (WriteResult(upParams.updatePackage[upParams.pkgLocation],
288fb299fa2Sopenharmony_ci        updateRet == UPDATE_SUCCESS ? "verify_success" : "verify_fail") != UPDATE_SUCCESS) {
289fb299fa2Sopenharmony_ci        LOG(ERROR) << "write update state fail";
290fb299fa2Sopenharmony_ci    }
291fb299fa2Sopenharmony_ci    return updateRet;
292fb299fa2Sopenharmony_ci}
293fb299fa2Sopenharmony_ci
294fb299fa2Sopenharmony_cinamespace {
295fb299fa2Sopenharmony_civoid SetProgress(const std::vector<std::string> &output, UpdaterParams &upParams)
296fb299fa2Sopenharmony_ci{
297fb299fa2Sopenharmony_ci    if (upParams.callbackProgress == nullptr) {
298fb299fa2Sopenharmony_ci        LOG(ERROR) << "CallbackProgress is nullptr";
299fb299fa2Sopenharmony_ci        return;
300fb299fa2Sopenharmony_ci    }
301fb299fa2Sopenharmony_ci    if (output.size() < DEFAULT_PROCESS_NUM) {
302fb299fa2Sopenharmony_ci        LOG(ERROR) << "check output fail";
303fb299fa2Sopenharmony_ci        return;
304fb299fa2Sopenharmony_ci    }
305fb299fa2Sopenharmony_ci    auto outputInfo = Trim(output[1]);
306fb299fa2Sopenharmony_ci    float frac = std::stof(output[1]);
307fb299fa2Sopenharmony_ci    int tmpProgressValue = 0;
308fb299fa2Sopenharmony_ci    if (frac >= -EPSINON && frac <= EPSINON) {
309fb299fa2Sopenharmony_ci        return;
310fb299fa2Sopenharmony_ci    } else {
311fb299fa2Sopenharmony_ci        tmpProgressValue = static_cast<int>(frac * g_percentage);
312fb299fa2Sopenharmony_ci    }
313fb299fa2Sopenharmony_ci    if (frac >= FULL_EPSINON && g_tmpValue + g_percentage < FULL_PERCENT_PROGRESS) {
314fb299fa2Sopenharmony_ci        g_tmpValue += g_percentage;
315fb299fa2Sopenharmony_ci        g_tmpProgressValue = g_tmpValue;
316fb299fa2Sopenharmony_ci        upParams.callbackProgress(g_tmpProgressValue *
317fb299fa2Sopenharmony_ci            upParams.currentPercentage + upParams.initialProgress * FULL_PERCENT_PROGRESS);
318fb299fa2Sopenharmony_ci        return;
319fb299fa2Sopenharmony_ci    }
320fb299fa2Sopenharmony_ci    g_tmpProgressValue = tmpProgressValue + g_tmpValue;
321fb299fa2Sopenharmony_ci    if (g_tmpProgressValue == 0) {
322fb299fa2Sopenharmony_ci        return;
323fb299fa2Sopenharmony_ci    }
324fb299fa2Sopenharmony_ci    upParams.callbackProgress(g_tmpProgressValue *
325fb299fa2Sopenharmony_ci        upParams.currentPercentage + upParams.initialProgress * FULL_PERCENT_PROGRESS);
326fb299fa2Sopenharmony_ci}
327fb299fa2Sopenharmony_ci}
328fb299fa2Sopenharmony_ci
329fb299fa2Sopenharmony_civoid HandleChildOutput(const std::string &buffer, int32_t bufferLen, bool &retryUpdate, UpdaterParams &upParams)
330fb299fa2Sopenharmony_ci{
331fb299fa2Sopenharmony_ci    if (bufferLen == 0) {
332fb299fa2Sopenharmony_ci        return;
333fb299fa2Sopenharmony_ci    }
334fb299fa2Sopenharmony_ci    std::string str = buffer;
335fb299fa2Sopenharmony_ci    std::vector<std::string> output = SplitString(str, ":");
336fb299fa2Sopenharmony_ci    if (output.size() < DEFAULT_PROCESS_NUM) {
337fb299fa2Sopenharmony_ci        LOG(ERROR) << "check output fail";
338fb299fa2Sopenharmony_ci        return;
339fb299fa2Sopenharmony_ci    }
340fb299fa2Sopenharmony_ci    auto outputHeader = Trim(output[0]);
341fb299fa2Sopenharmony_ci    if (outputHeader == "write_log") {
342fb299fa2Sopenharmony_ci        auto outputInfo = Trim(output[1]);
343fb299fa2Sopenharmony_ci        LOG(INFO) << outputInfo;
344fb299fa2Sopenharmony_ci    } else if (outputHeader == "retry_update") {
345fb299fa2Sopenharmony_ci        retryUpdate = true;
346fb299fa2Sopenharmony_ci        auto outputInfo = Trim(output[1]);
347fb299fa2Sopenharmony_ci        HwFaultRetry::GetInstance().SetFaultInfo(outputInfo);
348fb299fa2Sopenharmony_ci    } else if (outputHeader == "ui_log") {
349fb299fa2Sopenharmony_ci        auto outputInfo = Trim(output[1]);
350fb299fa2Sopenharmony_ci    } else if (outputHeader == "show_progress") {
351fb299fa2Sopenharmony_ci        g_tmpValue = g_tmpProgressValue;
352fb299fa2Sopenharmony_ci        auto outputInfo = Trim(output[1]);
353fb299fa2Sopenharmony_ci        float frac;
354fb299fa2Sopenharmony_ci        std::vector<std::string> progress = SplitString(outputInfo, ",");
355fb299fa2Sopenharmony_ci        if (progress.size() != DEFAULT_PROCESS_NUM) {
356fb299fa2Sopenharmony_ci            LOG(ERROR) << "show progress with wrong arguments";
357fb299fa2Sopenharmony_ci        } else {
358fb299fa2Sopenharmony_ci            frac = std::stof(progress[0]);
359fb299fa2Sopenharmony_ci            g_percentage = static_cast<int>(frac * FULL_PERCENT_PROGRESS);
360fb299fa2Sopenharmony_ci        }
361fb299fa2Sopenharmony_ci    } else if (outputHeader == "set_progress") {
362fb299fa2Sopenharmony_ci        SetProgress(output, upParams);
363fb299fa2Sopenharmony_ci    } else {
364fb299fa2Sopenharmony_ci        LOG(WARNING) << "Child process returns unexpected message.";
365fb299fa2Sopenharmony_ci    }
366fb299fa2Sopenharmony_ci}
367fb299fa2Sopenharmony_ci
368fb299fa2Sopenharmony_civoid ExcuteSubProc(const UpdaterParams &upParams, const std::string &fullPath, int pipeWrite)
369fb299fa2Sopenharmony_ci{
370fb299fa2Sopenharmony_ci    // Set process scheduler to normal if current scheduler is
371fb299fa2Sopenharmony_ci    // SCHED_FIFO, which may cause bad performance.
372fb299fa2Sopenharmony_ci    int policy = syscall(SYS_sched_getscheduler, getpid());
373fb299fa2Sopenharmony_ci    if (policy == -1) {
374fb299fa2Sopenharmony_ci        LOG(INFO) << "Cannnot get current process scheduler";
375fb299fa2Sopenharmony_ci    } else if (policy == SCHED_FIFO) {
376fb299fa2Sopenharmony_ci        LOG(DEBUG) << "Current process with scheduler SCHED_FIFO";
377fb299fa2Sopenharmony_ci        struct sched_param sp = {
378fb299fa2Sopenharmony_ci            .sched_priority = 0,
379fb299fa2Sopenharmony_ci        };
380fb299fa2Sopenharmony_ci        if (syscall(SYS_sched_setscheduler, getpid(), SCHED_OTHER, &sp) < 0) {
381fb299fa2Sopenharmony_ci            LOG(WARNING) << "Cannot set current process schedule with SCHED_OTHER";
382fb299fa2Sopenharmony_ci        }
383fb299fa2Sopenharmony_ci    }
384fb299fa2Sopenharmony_ci    const std::string retryPara = upParams.retryCount > 0 ? "retry=1" : "retry=0";
385fb299fa2Sopenharmony_ci    execl(fullPath.c_str(), fullPath.c_str(), upParams.updatePackage[upParams.pkgLocation].c_str(),
386fb299fa2Sopenharmony_ci            std::to_string(pipeWrite).c_str(), retryPara.c_str(), nullptr);
387fb299fa2Sopenharmony_ci    LOG(ERROR) << "Execute updater binary failed";
388fb299fa2Sopenharmony_ci    UPDATER_LAST_WORD(UPDATE_ERROR);
389fb299fa2Sopenharmony_ci    exit(-1);
390fb299fa2Sopenharmony_ci}
391fb299fa2Sopenharmony_ci
392fb299fa2Sopenharmony_ciUpdaterStatus HandlePipeMsg(UpdaterParams &upParams, int pipeRead, bool &retryUpdate)
393fb299fa2Sopenharmony_ci{
394fb299fa2Sopenharmony_ci    char buffer[MAX_BUFFER_SIZE] = {0};
395fb299fa2Sopenharmony_ci    FILE* fromChild = fdopen(pipeRead, "r");
396fb299fa2Sopenharmony_ci    if (fromChild == nullptr) {
397fb299fa2Sopenharmony_ci        LOG(ERROR) << "fdopen pipeRead failed";
398fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
399fb299fa2Sopenharmony_ci    }
400fb299fa2Sopenharmony_ci    while (fgets(buffer, MAX_BUFFER_SIZE - 1, fromChild) != nullptr) {
401fb299fa2Sopenharmony_ci        char *pch = strrchr(buffer, '\n');
402fb299fa2Sopenharmony_ci        if (pch != nullptr) {
403fb299fa2Sopenharmony_ci            *pch = '\0';
404fb299fa2Sopenharmony_ci        }
405fb299fa2Sopenharmony_ci        if (strstr(buffer, "subProcessResult") != nullptr) {
406fb299fa2Sopenharmony_ci            LOG(INFO) << "subProcessResult: " << buffer;
407fb299fa2Sopenharmony_ci            break;
408fb299fa2Sopenharmony_ci        }
409fb299fa2Sopenharmony_ci        HandleChildOutput(buffer, MAX_BUFFER_SIZE, retryUpdate, upParams);
410fb299fa2Sopenharmony_ci    }
411fb299fa2Sopenharmony_ci    LOG(INFO) << "HandlePipeMsg end";
412fb299fa2Sopenharmony_ci    fclose(fromChild);
413fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
414fb299fa2Sopenharmony_ci}
415fb299fa2Sopenharmony_ci
416fb299fa2Sopenharmony_ciUpdaterStatus CheckProcStatus(pid_t pid, bool retryUpdate)
417fb299fa2Sopenharmony_ci{
418fb299fa2Sopenharmony_ci    int status;
419fb299fa2Sopenharmony_ci    if (waitpid(pid, &status, 0) == -1) {
420fb299fa2Sopenharmony_ci        LOG(ERROR) << "waitpid error";
421fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
422fb299fa2Sopenharmony_ci    }
423fb299fa2Sopenharmony_ci    if (retryUpdate) {
424fb299fa2Sopenharmony_ci        return UPDATE_RETRY;
425fb299fa2Sopenharmony_ci    }
426fb299fa2Sopenharmony_ci
427fb299fa2Sopenharmony_ci    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
428fb299fa2Sopenharmony_ci        if (WIFEXITED(status)) {
429fb299fa2Sopenharmony_ci            LOG(ERROR) << "exited, status= " << WEXITSTATUS(status);
430fb299fa2Sopenharmony_ci        } else if (WIFSIGNALED(status)) {
431fb299fa2Sopenharmony_ci            LOG(ERROR) << "killed by signal " << WTERMSIG(status);
432fb299fa2Sopenharmony_ci        } else if (WIFSTOPPED(status)) {
433fb299fa2Sopenharmony_ci            LOG(ERROR) << "stopped by signal " << WSTOPSIG(status);
434fb299fa2Sopenharmony_ci        }
435fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
436fb299fa2Sopenharmony_ci    }
437fb299fa2Sopenharmony_ci    LOG(DEBUG) << "Updater process finished.";
438fb299fa2Sopenharmony_ci    return UPDATE_SUCCESS;
439fb299fa2Sopenharmony_ci}
440fb299fa2Sopenharmony_ci
441fb299fa2Sopenharmony_ciUpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, UpdaterParams &upParams)
442fb299fa2Sopenharmony_ci{
443fb299fa2Sopenharmony_ci    UPDATER_INIT_RECORD;
444fb299fa2Sopenharmony_ci    int pfd[DEFAULT_PIPE_NUM]; /* communication between parent and child */
445fb299fa2Sopenharmony_ci    if (pipe(pfd) < 0) {
446fb299fa2Sopenharmony_ci        LOG(ERROR) << "Create pipe failed: ";
447fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
448fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
449fb299fa2Sopenharmony_ci    }
450fb299fa2Sopenharmony_ci    if (pkgManager == nullptr) {
451fb299fa2Sopenharmony_ci        LOG(ERROR) << "pkgManager is nullptr";
452fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_CORRUPT);
453fb299fa2Sopenharmony_ci        return UPDATE_CORRUPT;
454fb299fa2Sopenharmony_ci    }
455fb299fa2Sopenharmony_ci
456fb299fa2Sopenharmony_ci    int pipeRead = pfd[0];
457fb299fa2Sopenharmony_ci    int pipeWrite = pfd[1];
458fb299fa2Sopenharmony_ci    std::string fullPath = GetWorkPath() + std::string(UPDATER_BINARY);
459fb299fa2Sopenharmony_ci    (void)Utils::DeleteFile(fullPath);
460fb299fa2Sopenharmony_ci
461fb299fa2Sopenharmony_ci    if (ExtractUpdaterBinary(pkgManager, upParams.updatePackage[upParams.pkgLocation], UPDATER_BINARY) != 0) {
462fb299fa2Sopenharmony_ci        LOG(INFO) << "There is no valid updater_binary in package, use updater_binary in device";
463fb299fa2Sopenharmony_ci        fullPath = "/bin/updater_binary";
464fb299fa2Sopenharmony_ci    }
465fb299fa2Sopenharmony_ci
466fb299fa2Sopenharmony_ci#ifdef UPDATER_UT
467fb299fa2Sopenharmony_ci    fullPath = "/data/updater/updater_binary";
468fb299fa2Sopenharmony_ci#endif
469fb299fa2Sopenharmony_ci
470fb299fa2Sopenharmony_ci    if (chmod(fullPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
471fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to change mode";
472fb299fa2Sopenharmony_ci    }
473fb299fa2Sopenharmony_ci
474fb299fa2Sopenharmony_ci#ifdef WITH_SELINUX
475fb299fa2Sopenharmony_ci    Restorecon(fullPath.c_str());
476fb299fa2Sopenharmony_ci#endif // WITH_SELINUX
477fb299fa2Sopenharmony_ci
478fb299fa2Sopenharmony_ci    pid_t pid = fork();
479fb299fa2Sopenharmony_ci    if (pid < 0) {
480fb299fa2Sopenharmony_ci        ERROR_CODE(CODE_FORK_FAIL);
481fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(UPDATE_ERROR);
482fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
483fb299fa2Sopenharmony_ci    }
484fb299fa2Sopenharmony_ci
485fb299fa2Sopenharmony_ci    if (pid == 0) { // child
486fb299fa2Sopenharmony_ci        #ifdef WITH_SELINUX
487fb299fa2Sopenharmony_ci        setcon("u:r:updater_binary:s0");
488fb299fa2Sopenharmony_ci        #endif // WITH_SELINUX
489fb299fa2Sopenharmony_ci        close(pipeRead);   // close read endpoint
490fb299fa2Sopenharmony_ci        ExcuteSubProc(upParams, fullPath, pipeWrite);
491fb299fa2Sopenharmony_ci    }
492fb299fa2Sopenharmony_ci
493fb299fa2Sopenharmony_ci    close(pipeWrite); // close write endpoint
494fb299fa2Sopenharmony_ci    bool retryUpdate = false;
495fb299fa2Sopenharmony_ci    if (HandlePipeMsg(upParams, pipeRead, retryUpdate) != UPDATE_SUCCESS) {
496fb299fa2Sopenharmony_ci        return UPDATE_ERROR;
497fb299fa2Sopenharmony_ci    }
498fb299fa2Sopenharmony_ci
499fb299fa2Sopenharmony_ci    return CheckProcStatus(pid, retryUpdate);
500fb299fa2Sopenharmony_ci}
501fb299fa2Sopenharmony_ci
502fb299fa2Sopenharmony_cistd::string GetWorkPath()
503fb299fa2Sopenharmony_ci{
504fb299fa2Sopenharmony_ci    if (Utils::IsUpdaterMode()) {
505fb299fa2Sopenharmony_ci        return G_WORK_PATH;
506fb299fa2Sopenharmony_ci    }
507fb299fa2Sopenharmony_ci
508fb299fa2Sopenharmony_ci    return std::string(SYS_INSTALLER_PATH) + "/";
509fb299fa2Sopenharmony_ci}
510fb299fa2Sopenharmony_ci} // namespace Updater
511