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