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 16fb299fa2Sopenharmony_ci#include "utils.h" 17fb299fa2Sopenharmony_ci#include <algorithm> 18fb299fa2Sopenharmony_ci#include <cerrno> 19fb299fa2Sopenharmony_ci#include <cstdint> 20fb299fa2Sopenharmony_ci#include <cstdlib> 21fb299fa2Sopenharmony_ci#include <dirent.h> 22fb299fa2Sopenharmony_ci#include <fcntl.h> 23fb299fa2Sopenharmony_ci#include <limits> 24fb299fa2Sopenharmony_ci#include <linux/reboot.h> 25fb299fa2Sopenharmony_ci#include <string> 26fb299fa2Sopenharmony_ci#include <sys/reboot.h> 27fb299fa2Sopenharmony_ci#include <sys/stat.h> 28fb299fa2Sopenharmony_ci#include <sys/syscall.h> 29fb299fa2Sopenharmony_ci#include <unistd.h> 30fb299fa2Sopenharmony_ci#include <vector> 31fb299fa2Sopenharmony_ci#include "fs_manager/mount.h" 32fb299fa2Sopenharmony_ci#include "init_reboot.h" 33fb299fa2Sopenharmony_ci#include "log/log.h" 34fb299fa2Sopenharmony_ci#include "misc_info/misc_info.h" 35fb299fa2Sopenharmony_ci#ifdef WITH_SELINUX 36fb299fa2Sopenharmony_ci#include <policycoreutils.h> 37fb299fa2Sopenharmony_ci#include "selinux/selinux.h" 38fb299fa2Sopenharmony_ci#endif 39fb299fa2Sopenharmony_ci#include "package/pkg_manager.h" 40fb299fa2Sopenharmony_ci#include "parameter.h" 41fb299fa2Sopenharmony_ci#include "securec.h" 42fb299fa2Sopenharmony_ci#include "updater/updater_const.h" 43fb299fa2Sopenharmony_ci#include "scope_guard.h" 44fb299fa2Sopenharmony_ci 45fb299fa2Sopenharmony_cinamespace Updater { 46fb299fa2Sopenharmony_ciusing namespace Hpackage; 47fb299fa2Sopenharmony_ci 48fb299fa2Sopenharmony_cinamespace Utils { 49fb299fa2Sopenharmony_ciconstexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4; 50fb299fa2Sopenharmony_ciconstexpr int MAX_TIME_SIZE = 20; 51fb299fa2Sopenharmony_ciconstexpr size_t PARAM_SIZE = 32; 52fb299fa2Sopenharmony_ciconstexpr const char *PREFIX_PARTITION_NODE = "/dev/block/by-name/"; 53fb299fa2Sopenharmony_ciconstexpr mode_t DEFAULT_DIR_MODE = 0775; 54fb299fa2Sopenharmony_ci 55fb299fa2Sopenharmony_cinamespace { 56fb299fa2Sopenharmony_civoid UpdateInfoInMisc(const std::string headInfo, const std::optional<int> message, bool isRemove) 57fb299fa2Sopenharmony_ci{ 58fb299fa2Sopenharmony_ci if (headInfo.empty()) { 59fb299fa2Sopenharmony_ci return; 60fb299fa2Sopenharmony_ci } 61fb299fa2Sopenharmony_ci std::vector<std::string> args = Utils::ParseParams(0, nullptr); 62fb299fa2Sopenharmony_ci struct UpdateMessage msg {}; 63fb299fa2Sopenharmony_ci if (!ReadUpdaterMiscMsg(msg)) { 64fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc read misc failed"; 65fb299fa2Sopenharmony_ci return; 66fb299fa2Sopenharmony_ci } 67fb299fa2Sopenharmony_ci 68fb299fa2Sopenharmony_ci (void)memset_s(msg.update, sizeof(msg.update), 0, sizeof(msg.update)); 69fb299fa2Sopenharmony_ci for (const auto& arg : args) { 70fb299fa2Sopenharmony_ci if (arg.find(headInfo) == std::string::npos) { 71fb299fa2Sopenharmony_ci if (strncat_s(msg.update, sizeof(msg.update), arg.c_str(), strlen(arg.c_str()) + 1) != EOK) { 72fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc strncat_s failed"; 73fb299fa2Sopenharmony_ci return; 74fb299fa2Sopenharmony_ci } 75fb299fa2Sopenharmony_ci if (strncat_s(msg.update, sizeof(msg.update), "\n", strlen("\n") + 1) != EOK) { 76fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc strncat_s failed"; 77fb299fa2Sopenharmony_ci return; 78fb299fa2Sopenharmony_ci } 79fb299fa2Sopenharmony_ci } 80fb299fa2Sopenharmony_ci } 81fb299fa2Sopenharmony_ci char buffer[128] {}; // 128 : set headInfo size 82fb299fa2Sopenharmony_ci if (isRemove) { 83fb299fa2Sopenharmony_ci LOG(INFO) << "remove --" << headInfo << " from misc"; 84fb299fa2Sopenharmony_ci } else if (!message.has_value()) { 85fb299fa2Sopenharmony_ci if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s", headInfo.c_str()) == -1) { 86fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc snprintf_s failed"; 87fb299fa2Sopenharmony_ci return; 88fb299fa2Sopenharmony_ci } 89fb299fa2Sopenharmony_ci } else { 90fb299fa2Sopenharmony_ci if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s=%d", 91fb299fa2Sopenharmony_ci headInfo.c_str(), message.value()) == -1) { 92fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc snprintf_s failed"; 93fb299fa2Sopenharmony_ci return; 94fb299fa2Sopenharmony_ci } 95fb299fa2Sopenharmony_ci } 96fb299fa2Sopenharmony_ci if (strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1) != EOK) { 97fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc strncat_s failed"; 98fb299fa2Sopenharmony_ci return; 99fb299fa2Sopenharmony_ci } 100fb299fa2Sopenharmony_ci if (WriteUpdaterMiscMsg(msg) != true) { 101fb299fa2Sopenharmony_ci LOG(ERROR) << "Write command to misc failed."; 102fb299fa2Sopenharmony_ci } 103fb299fa2Sopenharmony_ci} 104fb299fa2Sopenharmony_ci} // namespace 105fb299fa2Sopenharmony_ci 106fb299fa2Sopenharmony_civoid SaveLogs() 107fb299fa2Sopenharmony_ci{ 108fb299fa2Sopenharmony_ci std::string updaterLogPath = std::string(UPDATER_LOG); 109fb299fa2Sopenharmony_ci std::string stageLogPath = std::string(UPDATER_STAGE_LOG); 110fb299fa2Sopenharmony_ci 111fb299fa2Sopenharmony_ci // save logs 112fb299fa2Sopenharmony_ci bool ret = CopyUpdaterLogs(TMP_LOG, updaterLogPath); 113fb299fa2Sopenharmony_ci if (!ret) { 114fb299fa2Sopenharmony_ci LOG(ERROR) << "Copy updater log failed!"; 115fb299fa2Sopenharmony_ci } 116fb299fa2Sopenharmony_ci 117fb299fa2Sopenharmony_ci mode_t mode = 0660; 118fb299fa2Sopenharmony_ci#ifndef __WIN32 119fb299fa2Sopenharmony_ci SetFileAttributes(updaterLogPath, USER_UPDATE_AUTHORITY, GROUP_UPDATE_AUTHORITY, mode); 120fb299fa2Sopenharmony_ci#endif 121fb299fa2Sopenharmony_ci 122fb299fa2Sopenharmony_ci STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater"; 123fb299fa2Sopenharmony_ci ret = CopyUpdaterLogs(TMP_STAGE_LOG, stageLogPath); 124fb299fa2Sopenharmony_ci chmod(stageLogPath.c_str(), mode); 125fb299fa2Sopenharmony_ci if (!ret) { 126fb299fa2Sopenharmony_ci LOG(ERROR) << "Copy stage log failed!"; 127fb299fa2Sopenharmony_ci } 128fb299fa2Sopenharmony_ci} 129fb299fa2Sopenharmony_ci 130fb299fa2Sopenharmony_ciint32_t DeleteFile(const std::string& filename) 131fb299fa2Sopenharmony_ci{ 132fb299fa2Sopenharmony_ci if (filename.empty()) { 133fb299fa2Sopenharmony_ci LOG(ERROR) << "Invalid filename"; 134fb299fa2Sopenharmony_ci return -1; 135fb299fa2Sopenharmony_ci } 136fb299fa2Sopenharmony_ci if (unlink(filename.c_str()) == -1 && errno != ENOENT) { 137fb299fa2Sopenharmony_ci LOG(ERROR) << "unlink " << filename << " failed"; 138fb299fa2Sopenharmony_ci return -1; 139fb299fa2Sopenharmony_ci } 140fb299fa2Sopenharmony_ci return 0; 141fb299fa2Sopenharmony_ci} 142fb299fa2Sopenharmony_ci 143fb299fa2Sopenharmony_cistd::vector<std::string> SplitString(const std::string &str, const std::string del) 144fb299fa2Sopenharmony_ci{ 145fb299fa2Sopenharmony_ci std::vector<std::string> result; 146fb299fa2Sopenharmony_ci size_t found = std::string::npos; 147fb299fa2Sopenharmony_ci size_t start = 0; 148fb299fa2Sopenharmony_ci while (true) { 149fb299fa2Sopenharmony_ci found = str.find_first_of(del, start); 150fb299fa2Sopenharmony_ci result.push_back(str.substr(start, found - start)); 151fb299fa2Sopenharmony_ci if (found == std::string::npos) { 152fb299fa2Sopenharmony_ci break; 153fb299fa2Sopenharmony_ci } 154fb299fa2Sopenharmony_ci start = found + 1; 155fb299fa2Sopenharmony_ci } 156fb299fa2Sopenharmony_ci return result; 157fb299fa2Sopenharmony_ci} 158fb299fa2Sopenharmony_ci 159fb299fa2Sopenharmony_cistd::string Trim(const std::string &str) 160fb299fa2Sopenharmony_ci{ 161fb299fa2Sopenharmony_ci if (str.empty()) { 162fb299fa2Sopenharmony_ci LOG(ERROR) << "str is empty"; 163fb299fa2Sopenharmony_ci return str; 164fb299fa2Sopenharmony_ci } 165fb299fa2Sopenharmony_ci size_t start = 0; 166fb299fa2Sopenharmony_ci size_t end = str.size() - 1; 167fb299fa2Sopenharmony_ci while (start < str.size()) { 168fb299fa2Sopenharmony_ci if (!isspace(str[start])) { 169fb299fa2Sopenharmony_ci break; 170fb299fa2Sopenharmony_ci } 171fb299fa2Sopenharmony_ci start++; 172fb299fa2Sopenharmony_ci } 173fb299fa2Sopenharmony_ci while (start < end) { 174fb299fa2Sopenharmony_ci if (!isspace(str[end])) { 175fb299fa2Sopenharmony_ci break; 176fb299fa2Sopenharmony_ci } 177fb299fa2Sopenharmony_ci end--; 178fb299fa2Sopenharmony_ci } 179fb299fa2Sopenharmony_ci if (end < start) { 180fb299fa2Sopenharmony_ci return ""; 181fb299fa2Sopenharmony_ci } 182fb299fa2Sopenharmony_ci return str.substr(start, end - start + 1); 183fb299fa2Sopenharmony_ci} 184fb299fa2Sopenharmony_ci 185fb299fa2Sopenharmony_cistd::string ConvertSha256Hex(const uint8_t* shaDigest, size_t length) 186fb299fa2Sopenharmony_ci{ 187fb299fa2Sopenharmony_ci const std::string hexChars = "0123456789abcdef"; 188fb299fa2Sopenharmony_ci std::string haxSha256 = ""; 189fb299fa2Sopenharmony_ci unsigned int c; 190fb299fa2Sopenharmony_ci for (size_t i = 0; i < length; ++i) { 191fb299fa2Sopenharmony_ci auto d = shaDigest[i]; 192fb299fa2Sopenharmony_ci c = (d >> SHIFT_RIGHT_FOUR_BITS) & 0xf; // last 4 bits 193fb299fa2Sopenharmony_ci haxSha256.push_back(hexChars[c]); 194fb299fa2Sopenharmony_ci haxSha256.push_back(hexChars[d & 0xf]); 195fb299fa2Sopenharmony_ci } 196fb299fa2Sopenharmony_ci return haxSha256; 197fb299fa2Sopenharmony_ci} 198fb299fa2Sopenharmony_ci 199fb299fa2Sopenharmony_cibool SetRebootMisc(const std::string& rebootTarget, const std::string &extData, struct UpdateMessage &msg) 200fb299fa2Sopenharmony_ci{ 201fb299fa2Sopenharmony_ci static const int32_t maxCommandSize = 16; 202fb299fa2Sopenharmony_ci int result = 0; 203fb299fa2Sopenharmony_ci if (rebootTarget == "updater" && strcmp(msg.command, "boot_updater") != 0) { 204fb299fa2Sopenharmony_ci result = strcpy_s(msg.command, maxCommandSize, "boot_updater"); 205fb299fa2Sopenharmony_ci } else if (rebootTarget == "flashd" && strcmp(msg.command, "flashd") != 0) { 206fb299fa2Sopenharmony_ci result = strcpy_s(msg.command, maxCommandSize, "boot_flash"); 207fb299fa2Sopenharmony_ci } else if (rebootTarget == "bootloader" && strcmp(msg.command, "boot_loader") != 0) { 208fb299fa2Sopenharmony_ci result = strcpy_s(msg.command, maxCommandSize, "boot_loader"); 209fb299fa2Sopenharmony_ci } 210fb299fa2Sopenharmony_ci if (result != EOK) { 211fb299fa2Sopenharmony_ci LOG(ERROR) << "reboot set misc strcpy failed"; 212fb299fa2Sopenharmony_ci return false; 213fb299fa2Sopenharmony_ci } 214fb299fa2Sopenharmony_ci msg.command[maxCommandSize] = 0; 215fb299fa2Sopenharmony_ci if (extData.empty()) { 216fb299fa2Sopenharmony_ci (void)memset_s(msg.update, sizeof(msg.update), 0, sizeof(msg.update)); 217fb299fa2Sopenharmony_ci return true; 218fb299fa2Sopenharmony_ci } 219fb299fa2Sopenharmony_ci if (strcpy_s(msg.update, sizeof(msg.update) - 1, extData.c_str()) != EOK) { 220fb299fa2Sopenharmony_ci LOG(ERROR) << "failed to copy update"; 221fb299fa2Sopenharmony_ci return false; 222fb299fa2Sopenharmony_ci } 223fb299fa2Sopenharmony_ci msg.update[sizeof(msg.update) - 1] = 0; 224fb299fa2Sopenharmony_ci return true; 225fb299fa2Sopenharmony_ci} 226fb299fa2Sopenharmony_ci 227fb299fa2Sopenharmony_civoid UpdaterDoReboot(const std::string& rebootTarget, const std::string &rebootReason, const std::string &extData) 228fb299fa2Sopenharmony_ci{ 229fb299fa2Sopenharmony_ci LOG(INFO) << ", rebootTarget: " << rebootTarget; 230fb299fa2Sopenharmony_ci LOG(INFO) << ", rebootReason: " << rebootReason; 231fb299fa2Sopenharmony_ci LoadFstab(); 232fb299fa2Sopenharmony_ci struct UpdateMessage msg = {}; 233fb299fa2Sopenharmony_ci if (rebootTarget.empty()) { 234fb299fa2Sopenharmony_ci if (WriteUpdaterMiscMsg(msg) != true) { 235fb299fa2Sopenharmony_ci LOG(INFO) << "UpdaterDoReboot: WriteUpdaterMessage empty error"; 236fb299fa2Sopenharmony_ci } 237fb299fa2Sopenharmony_ci } else { 238fb299fa2Sopenharmony_ci if (!ReadUpdaterMiscMsg(msg)) { 239fb299fa2Sopenharmony_ci LOG(ERROR) << "UpdaterDoReboot read misc failed"; 240fb299fa2Sopenharmony_ci } 241fb299fa2Sopenharmony_ci if (!SetRebootMisc(rebootTarget, extData, msg)) { 242fb299fa2Sopenharmony_ci LOG(ERROR) << "UpdaterDoReboot set misc failed"; 243fb299fa2Sopenharmony_ci } 244fb299fa2Sopenharmony_ci if (!WriteUpdaterMiscMsg(msg)) { 245fb299fa2Sopenharmony_ci LOG(INFO) << "UpdaterDoReboot: WriteUpdaterMiscMsg error"; 246fb299fa2Sopenharmony_ci } 247fb299fa2Sopenharmony_ci } 248fb299fa2Sopenharmony_ci sync(); 249fb299fa2Sopenharmony_ci#ifndef UPDATER_UT 250fb299fa2Sopenharmony_ci DoRebootExt(rebootTarget.c_str(), rebootReason.c_str()); 251fb299fa2Sopenharmony_ci while (true) { 252fb299fa2Sopenharmony_ci pause(); 253fb299fa2Sopenharmony_ci } 254fb299fa2Sopenharmony_ci#else 255fb299fa2Sopenharmony_ci return; 256fb299fa2Sopenharmony_ci#endif 257fb299fa2Sopenharmony_ci} 258fb299fa2Sopenharmony_ci 259fb299fa2Sopenharmony_civoid DoShutdown(const std::string &shutdownReason) 260fb299fa2Sopenharmony_ci{ 261fb299fa2Sopenharmony_ci UpdateMessage msg = {}; 262fb299fa2Sopenharmony_ci if (!WriteUpdaterMiscMsg(msg)) { 263fb299fa2Sopenharmony_ci LOG(ERROR) << "DoShutdown: WriteUpdaterMessage empty error"; 264fb299fa2Sopenharmony_ci return; 265fb299fa2Sopenharmony_ci } 266fb299fa2Sopenharmony_ci sync(); 267fb299fa2Sopenharmony_ci DoRebootExt("shutdown", shutdownReason.c_str()); 268fb299fa2Sopenharmony_ci} 269fb299fa2Sopenharmony_ci 270fb299fa2Sopenharmony_cistd::string GetCertName() 271fb299fa2Sopenharmony_ci{ 272fb299fa2Sopenharmony_ci#ifndef UPDATER_UT 273fb299fa2Sopenharmony_ci static std::string signingCertName = "/etc/certificate/signing_cert.crt"; 274fb299fa2Sopenharmony_ci#ifdef SIGN_ON_SERVER 275fb299fa2Sopenharmony_ci signingCertName = Updater::Utils::ON_SERVER; 276fb299fa2Sopenharmony_ci#endif 277fb299fa2Sopenharmony_ci#else 278fb299fa2Sopenharmony_ci static std::string signingCertName = "/data/updater/src/signing_cert.crt"; 279fb299fa2Sopenharmony_ci#endif 280fb299fa2Sopenharmony_ci return signingCertName; 281fb299fa2Sopenharmony_ci} 282fb299fa2Sopenharmony_ci 283fb299fa2Sopenharmony_cibool WriteFully(int fd, const uint8_t *data, size_t size) 284fb299fa2Sopenharmony_ci{ 285fb299fa2Sopenharmony_ci ssize_t written = 0; 286fb299fa2Sopenharmony_ci size_t rest = size; 287fb299fa2Sopenharmony_ci 288fb299fa2Sopenharmony_ci while (rest > 0) { 289fb299fa2Sopenharmony_ci do { 290fb299fa2Sopenharmony_ci written = write(fd, data, rest); 291fb299fa2Sopenharmony_ci } while (written < 0 && errno == EINTR); 292fb299fa2Sopenharmony_ci if (written < 0) { 293fb299fa2Sopenharmony_ci return false; 294fb299fa2Sopenharmony_ci } 295fb299fa2Sopenharmony_ci data += written; 296fb299fa2Sopenharmony_ci rest -= static_cast<size_t>(written); 297fb299fa2Sopenharmony_ci if (rest != 0) { 298fb299fa2Sopenharmony_ci LOG(INFO) << "totalSize = " << size << ", rest = " << rest; 299fb299fa2Sopenharmony_ci } 300fb299fa2Sopenharmony_ci } 301fb299fa2Sopenharmony_ci return true; 302fb299fa2Sopenharmony_ci} 303fb299fa2Sopenharmony_ci 304fb299fa2Sopenharmony_cibool ReadFully(int fd, void *data, size_t size) 305fb299fa2Sopenharmony_ci{ 306fb299fa2Sopenharmony_ci auto p = reinterpret_cast<uint8_t *>(data); 307fb299fa2Sopenharmony_ci size_t remaining = size; 308fb299fa2Sopenharmony_ci while (remaining > 0) { 309fb299fa2Sopenharmony_ci ssize_t sread = read(fd, p, remaining); 310fb299fa2Sopenharmony_ci if (sread == -1) { 311fb299fa2Sopenharmony_ci LOG(ERROR) << "read failed: " << strerror(errno); 312fb299fa2Sopenharmony_ci return false; 313fb299fa2Sopenharmony_ci } 314fb299fa2Sopenharmony_ci if (sread == 0) { 315fb299fa2Sopenharmony_ci LOG(ERROR) << "read reached unexpected EOF"; 316fb299fa2Sopenharmony_ci return false; 317fb299fa2Sopenharmony_ci } 318fb299fa2Sopenharmony_ci p += sread; 319fb299fa2Sopenharmony_ci remaining -= static_cast<size_t>(sread); 320fb299fa2Sopenharmony_ci } 321fb299fa2Sopenharmony_ci return true; 322fb299fa2Sopenharmony_ci} 323fb299fa2Sopenharmony_ci 324fb299fa2Sopenharmony_cibool ReadFileToString(int fd, std::string &content) 325fb299fa2Sopenharmony_ci{ 326fb299fa2Sopenharmony_ci struct stat sb {}; 327fb299fa2Sopenharmony_ci if (fstat(fd, &sb) != -1 && sb.st_size > 0) { 328fb299fa2Sopenharmony_ci content.resize(static_cast<size_t>(sb.st_size)); 329fb299fa2Sopenharmony_ci } 330fb299fa2Sopenharmony_ci ssize_t n; 331fb299fa2Sopenharmony_ci auto remaining = static_cast<size_t>(sb.st_size); 332fb299fa2Sopenharmony_ci auto p = reinterpret_cast<char *>(content.data()); 333fb299fa2Sopenharmony_ci while (remaining > 0) { 334fb299fa2Sopenharmony_ci n = read(fd, p, remaining); 335fb299fa2Sopenharmony_ci if (n <= 0) { 336fb299fa2Sopenharmony_ci return false; 337fb299fa2Sopenharmony_ci } 338fb299fa2Sopenharmony_ci p += n; 339fb299fa2Sopenharmony_ci remaining -= static_cast<size_t>(n); 340fb299fa2Sopenharmony_ci } 341fb299fa2Sopenharmony_ci return true; 342fb299fa2Sopenharmony_ci} 343fb299fa2Sopenharmony_ci 344fb299fa2Sopenharmony_cibool WriteStringToFile(int fd, const std::string& content) 345fb299fa2Sopenharmony_ci{ 346fb299fa2Sopenharmony_ci const char *p = content.data(); 347fb299fa2Sopenharmony_ci size_t remaining = content.size(); 348fb299fa2Sopenharmony_ci while (remaining > 0) { 349fb299fa2Sopenharmony_ci ssize_t n = write(fd, p, remaining); 350fb299fa2Sopenharmony_ci if (n == -1) { 351fb299fa2Sopenharmony_ci return false; 352fb299fa2Sopenharmony_ci } 353fb299fa2Sopenharmony_ci p += n; 354fb299fa2Sopenharmony_ci remaining -= static_cast<size_t>(n); 355fb299fa2Sopenharmony_ci } 356fb299fa2Sopenharmony_ci return true; 357fb299fa2Sopenharmony_ci} 358fb299fa2Sopenharmony_ci 359fb299fa2Sopenharmony_civoid SyncFile(const std::string &dst) 360fb299fa2Sopenharmony_ci{ 361fb299fa2Sopenharmony_ci int fd = open(dst.c_str(), O_RDWR); 362fb299fa2Sopenharmony_ci if (fd < 0) { 363fb299fa2Sopenharmony_ci LOG(ERROR) << "open " << dst << " failed! err " << strerror(errno); 364fb299fa2Sopenharmony_ci return; 365fb299fa2Sopenharmony_ci } 366fb299fa2Sopenharmony_ci fsync(fd); 367fb299fa2Sopenharmony_ci close(fd); 368fb299fa2Sopenharmony_ci} 369fb299fa2Sopenharmony_ci 370fb299fa2Sopenharmony_cibool CopyFile(const std::string &src, const std::string &dest, bool isAppend) 371fb299fa2Sopenharmony_ci{ 372fb299fa2Sopenharmony_ci char realPath[PATH_MAX + 1] = {0}; 373fb299fa2Sopenharmony_ci if (realpath(src.c_str(), realPath) == nullptr) { 374fb299fa2Sopenharmony_ci LOG(ERROR) << src << " get realpath fail"; 375fb299fa2Sopenharmony_ci return false; 376fb299fa2Sopenharmony_ci } 377fb299fa2Sopenharmony_ci 378fb299fa2Sopenharmony_ci std::ios_base::openmode mode = isAppend ? std::ios::app | std::ios::out : std::ios_base::out; 379fb299fa2Sopenharmony_ci std::ifstream fin(realPath); 380fb299fa2Sopenharmony_ci std::ofstream fout(dest, mode); 381fb299fa2Sopenharmony_ci if (!fin.is_open() || !fout.is_open()) { 382fb299fa2Sopenharmony_ci return false; 383fb299fa2Sopenharmony_ci } 384fb299fa2Sopenharmony_ci 385fb299fa2Sopenharmony_ci fout << fin.rdbuf(); 386fb299fa2Sopenharmony_ci if (fout.fail()) { 387fb299fa2Sopenharmony_ci fout.clear(); 388fb299fa2Sopenharmony_ci return false; 389fb299fa2Sopenharmony_ci } 390fb299fa2Sopenharmony_ci fout.flush(); 391fb299fa2Sopenharmony_ci fout.close(); 392fb299fa2Sopenharmony_ci SyncFile(dest); // no way to get fd from ofstream, so reopen to sync this file 393fb299fa2Sopenharmony_ci return true; 394fb299fa2Sopenharmony_ci} 395fb299fa2Sopenharmony_ci 396fb299fa2Sopenharmony_cibool CopyDir(const std::string &srcPath, const std::string &dstPath) 397fb299fa2Sopenharmony_ci{ 398fb299fa2Sopenharmony_ci DIR *dir = opendir(srcPath.c_str()); 399fb299fa2Sopenharmony_ci if (dir == nullptr) { 400fb299fa2Sopenharmony_ci LOG(ERROR) << "opendir failed, path: " << srcPath.c_str() << ", err: " << strerror(errno); 401fb299fa2Sopenharmony_ci return false; 402fb299fa2Sopenharmony_ci } 403fb299fa2Sopenharmony_ci ON_SCOPE_EXIT(closedir) { 404fb299fa2Sopenharmony_ci closedir(dir); 405fb299fa2Sopenharmony_ci }; 406fb299fa2Sopenharmony_ci bool existFlag = (access(dstPath.c_str(), 0) == 0); 407fb299fa2Sopenharmony_ci if ((!existFlag) && (mkdir(dstPath.c_str(), DEFAULT_DIR_MODE) != 0)) { 408fb299fa2Sopenharmony_ci LOG(ERROR) << "mkdir failed, path: " << dstPath.c_str() << ", err: " << strerror(errno); 409fb299fa2Sopenharmony_ci return false; 410fb299fa2Sopenharmony_ci } 411fb299fa2Sopenharmony_ci ON_SCOPE_EXIT(rmdir) { 412fb299fa2Sopenharmony_ci if (!existFlag) { 413fb299fa2Sopenharmony_ci remove(dstPath.c_str()); 414fb299fa2Sopenharmony_ci } 415fb299fa2Sopenharmony_ci }; 416fb299fa2Sopenharmony_ci dirent *dirent = nullptr; 417fb299fa2Sopenharmony_ci while ((dirent = readdir(dir)) != nullptr) { 418fb299fa2Sopenharmony_ci if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) { 419fb299fa2Sopenharmony_ci continue; 420fb299fa2Sopenharmony_ci } 421fb299fa2Sopenharmony_ci if (dirent->d_type == DT_DIR) { 422fb299fa2Sopenharmony_ci std::string fullSourcePath = srcPath + dirent->d_name + "/"; 423fb299fa2Sopenharmony_ci std::string fullDestPath = dstPath + dirent->d_name + "/"; 424fb299fa2Sopenharmony_ci if (!CopyDir(fullSourcePath, fullDestPath)) { 425fb299fa2Sopenharmony_ci LOG(ERROR) << "copydir failed, fullSourcePath: " << fullSourcePath.c_str() 426fb299fa2Sopenharmony_ci << ", fullDestPath: " << fullDestPath.c_str(); 427fb299fa2Sopenharmony_ci return false; 428fb299fa2Sopenharmony_ci } 429fb299fa2Sopenharmony_ci } else { 430fb299fa2Sopenharmony_ci std::string fullSourcePath = srcPath + dirent->d_name; 431fb299fa2Sopenharmony_ci std::string fullDestPath = dstPath + dirent->d_name; 432fb299fa2Sopenharmony_ci if (!CopyFile(fullSourcePath, fullDestPath)) { 433fb299fa2Sopenharmony_ci LOG(ERROR) << "copyfile failed, fullSourcePath: " << fullSourcePath.c_str() 434fb299fa2Sopenharmony_ci << ", fullDestPath: " << fullDestPath.c_str(); 435fb299fa2Sopenharmony_ci return false; 436fb299fa2Sopenharmony_ci } 437fb299fa2Sopenharmony_ci } 438fb299fa2Sopenharmony_ci } 439fb299fa2Sopenharmony_ci CANCEL_SCOPE_EXIT_GUARD(rmdir); 440fb299fa2Sopenharmony_ci return true; 441fb299fa2Sopenharmony_ci} 442fb299fa2Sopenharmony_ci 443fb299fa2Sopenharmony_cistd::string GetLocalBoardId() 444fb299fa2Sopenharmony_ci{ 445fb299fa2Sopenharmony_ci return "HI3516"; 446fb299fa2Sopenharmony_ci} 447fb299fa2Sopenharmony_ci 448fb299fa2Sopenharmony_ciint32_t CreateCompressLogFile(const std::string &pkgName, std::vector<std::pair<std::string, ZipFileInfo>> &files) 449fb299fa2Sopenharmony_ci{ 450fb299fa2Sopenharmony_ci PkgInfo pkgInfo; 451fb299fa2Sopenharmony_ci pkgInfo.signMethod = PKG_SIGN_METHOD_NONE; 452fb299fa2Sopenharmony_ci pkgInfo.digestMethod = PKG_SIGN_METHOD_NONE; 453fb299fa2Sopenharmony_ci pkgInfo.pkgType = PKG_PACK_TYPE_ZIP; 454fb299fa2Sopenharmony_ci PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance(); 455fb299fa2Sopenharmony_ci if (pkgManager == nullptr) { 456fb299fa2Sopenharmony_ci LOG(ERROR) << "pkgManager is nullptr"; 457fb299fa2Sopenharmony_ci return -1; 458fb299fa2Sopenharmony_ci } 459fb299fa2Sopenharmony_ci int32_t ret = pkgManager->CreatePackage(pkgName, GetCertName(), &pkgInfo, files); 460fb299fa2Sopenharmony_ci PkgManager::ReleasePackageInstance(pkgManager); 461fb299fa2Sopenharmony_ci return ret; 462fb299fa2Sopenharmony_ci} 463fb299fa2Sopenharmony_ci 464fb299fa2Sopenharmony_civoid CompressFiles(std::vector<std::string> &files, const std::string &zipFile) 465fb299fa2Sopenharmony_ci{ 466fb299fa2Sopenharmony_ci (void)DeleteFile(zipFile); 467fb299fa2Sopenharmony_ci std::vector<std::pair<std::string, ZipFileInfo>> zipFiles {}; 468fb299fa2Sopenharmony_ci for (auto path : files) { 469fb299fa2Sopenharmony_ci ZipFileInfo file {}; 470fb299fa2Sopenharmony_ci file.fileInfo.identity = path.substr(path.find_last_of("/") + 1); 471fb299fa2Sopenharmony_ci file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP; 472fb299fa2Sopenharmony_ci file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; 473fb299fa2Sopenharmony_ci zipFiles.push_back(std::pair<std::string, ZipFileInfo>(path, file)); 474fb299fa2Sopenharmony_ci } 475fb299fa2Sopenharmony_ci 476fb299fa2Sopenharmony_ci int32_t ret = CreateCompressLogFile(zipFile, zipFiles); 477fb299fa2Sopenharmony_ci if (ret != 0) { 478fb299fa2Sopenharmony_ci LOG(WARNING) << "CompressFiles failed: " << zipFile; 479fb299fa2Sopenharmony_ci return; 480fb299fa2Sopenharmony_ci } 481fb299fa2Sopenharmony_ci mode_t mode = 0660; 482fb299fa2Sopenharmony_ci#ifndef __WIN32 483fb299fa2Sopenharmony_ci SetFileAttributes(zipFile, USER_UPDATE_AUTHORITY, GROUP_SYS_AUTHORITY, mode); 484fb299fa2Sopenharmony_ci#endif 485fb299fa2Sopenharmony_ci} 486fb299fa2Sopenharmony_ci 487fb299fa2Sopenharmony_civoid CompressLogs(const std::string &logName) 488fb299fa2Sopenharmony_ci{ 489fb299fa2Sopenharmony_ci std::vector<std::pair<std::string, ZipFileInfo>> files; 490fb299fa2Sopenharmony_ci // Build the zip file to be packaged 491fb299fa2Sopenharmony_ci std::vector<std::string> testFileNames; 492fb299fa2Sopenharmony_ci std::string realName = logName.substr(logName.find_last_of("/") + 1); 493fb299fa2Sopenharmony_ci std::string logPath = logName.substr(0, logName.find_last_of("/")); 494fb299fa2Sopenharmony_ci testFileNames.push_back(realName); 495fb299fa2Sopenharmony_ci for (auto name : testFileNames) { 496fb299fa2Sopenharmony_ci ZipFileInfo file; 497fb299fa2Sopenharmony_ci file.fileInfo.identity = name; 498fb299fa2Sopenharmony_ci file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP; 499fb299fa2Sopenharmony_ci file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; 500fb299fa2Sopenharmony_ci std::string fileName = logName; 501fb299fa2Sopenharmony_ci files.push_back(std::pair<std::string, ZipFileInfo>(fileName, file)); 502fb299fa2Sopenharmony_ci } 503fb299fa2Sopenharmony_ci 504fb299fa2Sopenharmony_ci char realTime[MAX_TIME_SIZE] = {0}; 505fb299fa2Sopenharmony_ci auto sysTime = std::chrono::system_clock::now(); 506fb299fa2Sopenharmony_ci auto currentTime = std::chrono::system_clock::to_time_t(sysTime); 507fb299fa2Sopenharmony_ci struct tm *localTime = std::localtime(¤tTime); 508fb299fa2Sopenharmony_ci if (localTime != nullptr) { 509fb299fa2Sopenharmony_ci std::strftime(realTime, sizeof(realTime), "%Y%m%d%H%M%S", localTime); 510fb299fa2Sopenharmony_ci } 511fb299fa2Sopenharmony_ci char pkgName[MAX_LOG_NAME_SIZE]; 512fb299fa2Sopenharmony_ci if (snprintf_s(pkgName, MAX_LOG_NAME_SIZE, MAX_LOG_NAME_SIZE - 1, 513fb299fa2Sopenharmony_ci "%s/%s_%s.zip", logPath.c_str(), realName.c_str(), realTime) == -1) { 514fb299fa2Sopenharmony_ci return; 515fb299fa2Sopenharmony_ci } 516fb299fa2Sopenharmony_ci int32_t ret = CreateCompressLogFile(pkgName, files); 517fb299fa2Sopenharmony_ci if (ret != 0) { 518fb299fa2Sopenharmony_ci LOG(WARNING) << "CompressLogs failed"; 519fb299fa2Sopenharmony_ci return; 520fb299fa2Sopenharmony_ci } 521fb299fa2Sopenharmony_ci mode_t mode = 0660; 522fb299fa2Sopenharmony_ci#ifndef __WIN32 523fb299fa2Sopenharmony_ci SetFileAttributes(pkgName, USER_UPDATE_AUTHORITY, GROUP_SYS_AUTHORITY, mode); 524fb299fa2Sopenharmony_ci#endif 525fb299fa2Sopenharmony_ci sync(); 526fb299fa2Sopenharmony_ci if (access(pkgName, 0) != 0) { 527fb299fa2Sopenharmony_ci LOG(ERROR) << "Failed to create zipfile: " << pkgName; 528fb299fa2Sopenharmony_ci } else { 529fb299fa2Sopenharmony_ci (void)DeleteFile(logName); 530fb299fa2Sopenharmony_ci } 531fb299fa2Sopenharmony_ci} 532fb299fa2Sopenharmony_ci 533fb299fa2Sopenharmony_cisize_t GetFileSize(const std::string &filePath) 534fb299fa2Sopenharmony_ci{ 535fb299fa2Sopenharmony_ci size_t ret = 0; 536fb299fa2Sopenharmony_ci std::ifstream ifs(filePath, std::ios::binary | std::ios::in); 537fb299fa2Sopenharmony_ci if (ifs.is_open()) { 538fb299fa2Sopenharmony_ci ifs.seekg(0, std::ios::end); 539fb299fa2Sopenharmony_ci ret = static_cast<size_t>(ifs.tellg()); 540fb299fa2Sopenharmony_ci } 541fb299fa2Sopenharmony_ci return ret; 542fb299fa2Sopenharmony_ci} 543fb299fa2Sopenharmony_ci 544fb299fa2Sopenharmony_cibool RestoreconPath(const std::string &path) 545fb299fa2Sopenharmony_ci{ 546fb299fa2Sopenharmony_ci if (MountForPath(path) != 0) { 547fb299fa2Sopenharmony_ci LOG(ERROR) << "MountForPath " << path << " failed!"; 548fb299fa2Sopenharmony_ci return false; 549fb299fa2Sopenharmony_ci } 550fb299fa2Sopenharmony_ci#ifdef WITH_SELINUX 551fb299fa2Sopenharmony_ci if (RestoreconRecurse(path.c_str()) == -1) { 552fb299fa2Sopenharmony_ci LOG(WARNING) << "restore " << path << " failed"; 553fb299fa2Sopenharmony_ci } 554fb299fa2Sopenharmony_ci#endif // WITH_SELINUX 555fb299fa2Sopenharmony_ci if (UmountForPath(path) != 0) { 556fb299fa2Sopenharmony_ci LOG(WARNING) << "UmountForPath " << path << " failed!"; 557fb299fa2Sopenharmony_ci } 558fb299fa2Sopenharmony_ci return true; 559fb299fa2Sopenharmony_ci} 560fb299fa2Sopenharmony_ci 561fb299fa2Sopenharmony_cibool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog) 562fb299fa2Sopenharmony_ci{ 563fb299fa2Sopenharmony_ci std::size_t found = dLog.find_last_of("/"); 564fb299fa2Sopenharmony_ci if (found == std::string::npos) { 565fb299fa2Sopenharmony_ci LOG(ERROR) << "Dest filePath error"; 566fb299fa2Sopenharmony_ci return false; 567fb299fa2Sopenharmony_ci } 568fb299fa2Sopenharmony_ci std::string destPath = dLog.substr(0, found); 569fb299fa2Sopenharmony_ci if (MountForPath(destPath) != 0) { 570fb299fa2Sopenharmony_ci LOG(WARNING) << "MountForPath /data/log failed!"; 571fb299fa2Sopenharmony_ci } 572fb299fa2Sopenharmony_ci 573fb299fa2Sopenharmony_ci if (access(destPath.c_str(), 0) != 0) { 574fb299fa2Sopenharmony_ci if (MkdirRecursive(destPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { 575fb299fa2Sopenharmony_ci LOG(ERROR) << "MkdirRecursive error!"; 576fb299fa2Sopenharmony_ci return false; 577fb299fa2Sopenharmony_ci } 578fb299fa2Sopenharmony_ci #ifdef WITH_SELINUX 579fb299fa2Sopenharmony_ci RestoreconRecurse(UPDATER_PATH); 580fb299fa2Sopenharmony_ci #endif // WITH_SELINUX 581fb299fa2Sopenharmony_ci } 582fb299fa2Sopenharmony_ci 583fb299fa2Sopenharmony_ci if (Utils::GetFileSize(sLog) > MAX_LOG_SIZE) { 584fb299fa2Sopenharmony_ci LOG(ERROR) << "Size bigger for" << sLog; 585fb299fa2Sopenharmony_ci STAGE(UPDATE_STAGE_FAIL) << "Log file error, unable to copy"; 586fb299fa2Sopenharmony_ci return false; 587fb299fa2Sopenharmony_ci } 588fb299fa2Sopenharmony_ci 589fb299fa2Sopenharmony_ci while (Utils::GetFileSize(sLog) + GetDirSizeForFile(dLog) > MAX_LOG_DIR_SIZE) { 590fb299fa2Sopenharmony_ci if (DeleteOldFile(destPath) != true) { 591fb299fa2Sopenharmony_ci break; 592fb299fa2Sopenharmony_ci } 593fb299fa2Sopenharmony_ci } 594fb299fa2Sopenharmony_ci 595fb299fa2Sopenharmony_ci if (!CopyFile(sLog, dLog, true)) { 596fb299fa2Sopenharmony_ci LOG(ERROR) << "copy log file failed."; 597fb299fa2Sopenharmony_ci return false; 598fb299fa2Sopenharmony_ci } 599fb299fa2Sopenharmony_ci if (GetFileSize(dLog) >= MAX_LOG_SIZE) { 600fb299fa2Sopenharmony_ci LOG(INFO) << "log size greater than 5M!"; 601fb299fa2Sopenharmony_ci CompressLogs(dLog); 602fb299fa2Sopenharmony_ci } 603fb299fa2Sopenharmony_ci sync(); 604fb299fa2Sopenharmony_ci return true; 605fb299fa2Sopenharmony_ci} 606fb299fa2Sopenharmony_ci 607fb299fa2Sopenharmony_cibool CheckResultFail() 608fb299fa2Sopenharmony_ci{ 609fb299fa2Sopenharmony_ci std::ifstream ifs; 610fb299fa2Sopenharmony_ci const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE); 611fb299fa2Sopenharmony_ci ifs.open(resultPath, std::ios::in); 612fb299fa2Sopenharmony_ci std::string buff; 613fb299fa2Sopenharmony_ci while (ifs.is_open() && getline(ifs, buff)) { 614fb299fa2Sopenharmony_ci if (buff.find("fail|") != std::string::npos) { 615fb299fa2Sopenharmony_ci ifs.close(); 616fb299fa2Sopenharmony_ci return true; 617fb299fa2Sopenharmony_ci } 618fb299fa2Sopenharmony_ci } 619fb299fa2Sopenharmony_ci LOG(ERROR) << "open result file failed"; 620fb299fa2Sopenharmony_ci return false; 621fb299fa2Sopenharmony_ci} 622fb299fa2Sopenharmony_ci 623fb299fa2Sopenharmony_civoid WriteDumpResult(const std::string &result, const std::string &fileName) 624fb299fa2Sopenharmony_ci{ 625fb299fa2Sopenharmony_ci if (access(UPDATER_PATH, 0) != 0) { 626fb299fa2Sopenharmony_ci if (MkdirRecursive(UPDATER_PATH, 0755) != 0) { // 0755: -rwxr-xr-x 627fb299fa2Sopenharmony_ci LOG(ERROR) << "MkdirRecursive error!"; 628fb299fa2Sopenharmony_ci return; 629fb299fa2Sopenharmony_ci } 630fb299fa2Sopenharmony_ci } 631fb299fa2Sopenharmony_ci LOG(INFO) << "WriteDumpResult: " << result; 632fb299fa2Sopenharmony_ci const std::string resultPath = std::string(UPDATER_PATH) + "/" + fileName; 633fb299fa2Sopenharmony_ci FILE *fp = fopen(resultPath.c_str(), "w+"); 634fb299fa2Sopenharmony_ci if (fp == nullptr) { 635fb299fa2Sopenharmony_ci LOG(ERROR) << "open result file failed"; 636fb299fa2Sopenharmony_ci return; 637fb299fa2Sopenharmony_ci } 638fb299fa2Sopenharmony_ci char buf[MAX_RESULT_BUFF_SIZE] = "Pass\n"; 639fb299fa2Sopenharmony_ci if (sprintf_s(buf, MAX_RESULT_BUFF_SIZE - 1, "%s\n", result.c_str()) < 0) { 640fb299fa2Sopenharmony_ci LOG(WARNING) << "sprintf status fialed"; 641fb299fa2Sopenharmony_ci } 642fb299fa2Sopenharmony_ci if (fwrite(buf, 1, strlen(buf) + 1, fp) <= 0) { 643fb299fa2Sopenharmony_ci LOG(WARNING) << "write result file failed, err:" << errno; 644fb299fa2Sopenharmony_ci } 645fb299fa2Sopenharmony_ci if (fclose(fp) != 0) { 646fb299fa2Sopenharmony_ci LOG(WARNING) << "close result file failed"; 647fb299fa2Sopenharmony_ci } 648fb299fa2Sopenharmony_ci 649fb299fa2Sopenharmony_ci (void)chown(resultPath.c_str(), USER_ROOT_AUTHORITY, GROUP_UPDATE_AUTHORITY); 650fb299fa2Sopenharmony_ci (void)chmod(resultPath.c_str(), 0660); // 0660: -rw-rw---- 651fb299fa2Sopenharmony_ci} 652fb299fa2Sopenharmony_ci 653fb299fa2Sopenharmony_cilong long int GetDirSize(const std::string &folderPath) 654fb299fa2Sopenharmony_ci{ 655fb299fa2Sopenharmony_ci DIR* dir = opendir(folderPath.c_str()); 656fb299fa2Sopenharmony_ci if (dir == nullptr) { 657fb299fa2Sopenharmony_ci LOG(ERROR) << "Failed to open folder: " << folderPath << std::endl; 658fb299fa2Sopenharmony_ci return 0; 659fb299fa2Sopenharmony_ci } 660fb299fa2Sopenharmony_ci 661fb299fa2Sopenharmony_ci struct dirent* entry; 662fb299fa2Sopenharmony_ci long long int totalSize = 0; 663fb299fa2Sopenharmony_ci while ((entry = readdir(dir)) != nullptr) { 664fb299fa2Sopenharmony_ci std::string fileName = entry->d_name; 665fb299fa2Sopenharmony_ci std::string filePath = folderPath + "/" + fileName; 666fb299fa2Sopenharmony_ci struct stat fileStat; 667fb299fa2Sopenharmony_ci if (stat(filePath.c_str(), &fileStat) != 0) { 668fb299fa2Sopenharmony_ci LOG(ERROR) << "Failed to get file status: " << filePath << std::endl; 669fb299fa2Sopenharmony_ci continue; 670fb299fa2Sopenharmony_ci } 671fb299fa2Sopenharmony_ci if (S_ISDIR(fileStat.st_mode)) { 672fb299fa2Sopenharmony_ci if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { 673fb299fa2Sopenharmony_ci continue; 674fb299fa2Sopenharmony_ci } 675fb299fa2Sopenharmony_ci std::string subFolderPath = filePath; 676fb299fa2Sopenharmony_ci totalSize += GetDirSize(subFolderPath); 677fb299fa2Sopenharmony_ci } else { 678fb299fa2Sopenharmony_ci totalSize += fileStat.st_size; 679fb299fa2Sopenharmony_ci } 680fb299fa2Sopenharmony_ci } 681fb299fa2Sopenharmony_ci closedir(dir); 682fb299fa2Sopenharmony_ci return totalSize; 683fb299fa2Sopenharmony_ci} 684fb299fa2Sopenharmony_ci 685fb299fa2Sopenharmony_cilong long int GetDirSizeForFile(const std::string &filePath) 686fb299fa2Sopenharmony_ci{ 687fb299fa2Sopenharmony_ci std::size_t found = filePath.find_last_of("/"); 688fb299fa2Sopenharmony_ci if (found == std::string::npos) { 689fb299fa2Sopenharmony_ci LOG(ERROR) << "filePath error"; 690fb299fa2Sopenharmony_ci return -1; 691fb299fa2Sopenharmony_ci } 692fb299fa2Sopenharmony_ci return GetDirSize(filePath.substr(0, found)); 693fb299fa2Sopenharmony_ci} 694fb299fa2Sopenharmony_ci 695fb299fa2Sopenharmony_cibool DeleteOldFile(const std::string folderPath) 696fb299fa2Sopenharmony_ci{ 697fb299fa2Sopenharmony_ci DIR* dir = opendir(folderPath.c_str()); 698fb299fa2Sopenharmony_ci if (dir == nullptr) { 699fb299fa2Sopenharmony_ci LOG(ERROR) << "Failed to open folder: " << folderPath << std::endl; 700fb299fa2Sopenharmony_ci return false; 701fb299fa2Sopenharmony_ci } 702fb299fa2Sopenharmony_ci 703fb299fa2Sopenharmony_ci struct dirent* entry; 704fb299fa2Sopenharmony_ci std::string oldestFilePath = ""; 705fb299fa2Sopenharmony_ci time_t oldestFileTime = std::numeric_limits<time_t>::max(); 706fb299fa2Sopenharmony_ci while ((entry = readdir(dir)) != nullptr) { 707fb299fa2Sopenharmony_ci std::string fileName = entry->d_name; 708fb299fa2Sopenharmony_ci std::string filePath = folderPath + "/" + fileName; 709fb299fa2Sopenharmony_ci struct stat fileStat; 710fb299fa2Sopenharmony_ci if (stat(filePath.c_str(), &fileStat) != 0) { 711fb299fa2Sopenharmony_ci LOG(ERROR) << "Failed to get file status: " << filePath; 712fb299fa2Sopenharmony_ci continue; 713fb299fa2Sopenharmony_ci } 714fb299fa2Sopenharmony_ci if (fileName == "." || fileName == "..") { 715fb299fa2Sopenharmony_ci continue; 716fb299fa2Sopenharmony_ci } 717fb299fa2Sopenharmony_ci if (fileStat.st_mtime < oldestFileTime) { 718fb299fa2Sopenharmony_ci oldestFileTime = fileStat.st_mtime; 719fb299fa2Sopenharmony_ci oldestFilePath = filePath; 720fb299fa2Sopenharmony_ci } 721fb299fa2Sopenharmony_ci } 722fb299fa2Sopenharmony_ci closedir(dir); 723fb299fa2Sopenharmony_ci if (oldestFilePath.empty()) { 724fb299fa2Sopenharmony_ci LOG(ERROR) << "Unable to delete file"; 725fb299fa2Sopenharmony_ci return false; 726fb299fa2Sopenharmony_ci } 727fb299fa2Sopenharmony_ci size_t size = GetFileSize(oldestFilePath); 728fb299fa2Sopenharmony_ci if (remove(oldestFilePath.c_str()) != 0) { 729fb299fa2Sopenharmony_ci LOG(ERROR) << "Failed to delete file: " << oldestFilePath; 730fb299fa2Sopenharmony_ci return false; 731fb299fa2Sopenharmony_ci } 732fb299fa2Sopenharmony_ci LOG(INFO) << "Delete old file: " << oldestFilePath << " size: " << size; 733fb299fa2Sopenharmony_ci return true; 734fb299fa2Sopenharmony_ci} 735fb299fa2Sopenharmony_ci 736fb299fa2Sopenharmony_cistd::vector<std::string> ParseParams(int argc, char **argv) 737fb299fa2Sopenharmony_ci{ 738fb299fa2Sopenharmony_ci struct UpdateMessage boot {}; 739fb299fa2Sopenharmony_ci // read from misc 740fb299fa2Sopenharmony_ci if (!ReadUpdaterMiscMsg(boot)) { 741fb299fa2Sopenharmony_ci LOG(ERROR) << "ReadUpdaterMessage MISC_FILE failed!"; 742fb299fa2Sopenharmony_ci } 743fb299fa2Sopenharmony_ci // if boot.update is empty, read from command.The Misc partition may have dirty data, 744fb299fa2Sopenharmony_ci // so strlen(boot.update) is not used, which can cause system exceptions. 745fb299fa2Sopenharmony_ci if (boot.update[0] == '\0' && !access(COMMAND_FILE, 0)) { 746fb299fa2Sopenharmony_ci if (!ReadUpdaterMessage(COMMAND_FILE, boot)) { 747fb299fa2Sopenharmony_ci LOG(ERROR) << "ReadUpdaterMessage COMMAND_FILE failed!"; 748fb299fa2Sopenharmony_ci } 749fb299fa2Sopenharmony_ci } 750fb299fa2Sopenharmony_ci 751fb299fa2Sopenharmony_ci boot.update[sizeof(boot.update) - 1] = '\0'; 752fb299fa2Sopenharmony_ci std::vector<std::string> parseParams = Utils::SplitString(boot.update, "\n"); 753fb299fa2Sopenharmony_ci if (argc != 0 && argv != nullptr) { 754fb299fa2Sopenharmony_ci parseParams.insert(parseParams.begin(), argv, argv + argc); 755fb299fa2Sopenharmony_ci } 756fb299fa2Sopenharmony_ci return parseParams; 757fb299fa2Sopenharmony_ci} 758fb299fa2Sopenharmony_ci 759fb299fa2Sopenharmony_cistd::string TrimUpdateMode(const std::string &mode) 760fb299fa2Sopenharmony_ci{ 761fb299fa2Sopenharmony_ci std::string optEqual = "="; 762fb299fa2Sopenharmony_ci std::string modePrefix = "--"; // misc = --update_package=xxxx / --sdcard_update 763fb299fa2Sopenharmony_ci size_t optPos = mode.size(); 764fb299fa2Sopenharmony_ci size_t prefixPos = 0; 765fb299fa2Sopenharmony_ci if (mode.empty() || mode == "") { 766fb299fa2Sopenharmony_ci return ""; 767fb299fa2Sopenharmony_ci } 768fb299fa2Sopenharmony_ci if (mode.find(optEqual) != std::string::npos) { 769fb299fa2Sopenharmony_ci optPos = mode.find(optEqual); 770fb299fa2Sopenharmony_ci } 771fb299fa2Sopenharmony_ci if (mode.find(modePrefix) != std::string::npos) { 772fb299fa2Sopenharmony_ci prefixPos = mode.find(modePrefix) + modePrefix.size(); 773fb299fa2Sopenharmony_ci } 774fb299fa2Sopenharmony_ci if (optPos < prefixPos) { 775fb299fa2Sopenharmony_ci return mode; 776fb299fa2Sopenharmony_ci } 777fb299fa2Sopenharmony_ci return mode.substr(prefixPos, optPos - prefixPos); 778fb299fa2Sopenharmony_ci} 779fb299fa2Sopenharmony_ci 780fb299fa2Sopenharmony_cibool CheckUpdateMode(const std::string &mode) 781fb299fa2Sopenharmony_ci{ 782fb299fa2Sopenharmony_ci std::vector<std::string> args = ParseParams(0, nullptr); 783fb299fa2Sopenharmony_ci for (const auto &arg : args) { 784fb299fa2Sopenharmony_ci if (TrimUpdateMode(arg) == mode) { 785fb299fa2Sopenharmony_ci return true; 786fb299fa2Sopenharmony_ci } 787fb299fa2Sopenharmony_ci } 788fb299fa2Sopenharmony_ci return false; 789fb299fa2Sopenharmony_ci} 790fb299fa2Sopenharmony_ci 791fb299fa2Sopenharmony_cistd::string DurationToString(std::vector<std::chrono::duration<double>> &durations, std::size_t pkgPosition, 792fb299fa2Sopenharmony_ci int precision) 793fb299fa2Sopenharmony_ci{ 794fb299fa2Sopenharmony_ci if (pkgPosition >= durations.size()) { 795fb299fa2Sopenharmony_ci LOG(ERROR) << "pkg position is " << pkgPosition << ", duration's size is " << durations.size(); 796fb299fa2Sopenharmony_ci return "0"; 797fb299fa2Sopenharmony_ci } 798fb299fa2Sopenharmony_ci std::ostringstream oss; 799fb299fa2Sopenharmony_ci oss << std::fixed << std::setprecision(precision) << durations[pkgPosition].count(); 800fb299fa2Sopenharmony_ci return oss.str(); 801fb299fa2Sopenharmony_ci} 802fb299fa2Sopenharmony_ci 803fb299fa2Sopenharmony_cistd::string GetRealPath(const std::string &path) 804fb299fa2Sopenharmony_ci{ 805fb299fa2Sopenharmony_ci char realPath[PATH_MAX + 1] = {0}; 806fb299fa2Sopenharmony_ci auto ret = realpath(path.c_str(), realPath); 807fb299fa2Sopenharmony_ci return (ret == nullptr) ? "" : ret; 808fb299fa2Sopenharmony_ci} 809fb299fa2Sopenharmony_ci 810fb299fa2Sopenharmony_cistd::string GetPartitionRealPath(const std::string &name) 811fb299fa2Sopenharmony_ci{ 812fb299fa2Sopenharmony_ci return GetRealPath(PREFIX_PARTITION_NODE + name); 813fb299fa2Sopenharmony_ci} 814fb299fa2Sopenharmony_ci 815fb299fa2Sopenharmony_civoid SetMessageToMisc(const std::string &miscCmd, const int message, const std::string headInfo) 816fb299fa2Sopenharmony_ci{ 817fb299fa2Sopenharmony_ci if (headInfo.empty()) { 818fb299fa2Sopenharmony_ci return; 819fb299fa2Sopenharmony_ci } 820fb299fa2Sopenharmony_ci std::vector<std::string> args = ParseParams(0, nullptr); 821fb299fa2Sopenharmony_ci struct UpdateMessage msg {}; 822fb299fa2Sopenharmony_ci if (!ReadUpdaterMiscMsg(msg)) { 823fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc read misc failed"; 824fb299fa2Sopenharmony_ci return; 825fb299fa2Sopenharmony_ci } 826fb299fa2Sopenharmony_ci (void)memset_s(msg.command, sizeof(msg.command), 0, sizeof(msg.command)); 827fb299fa2Sopenharmony_ci if (strncpy_s(msg.command, sizeof(msg.command), miscCmd.c_str(), miscCmd.size() + 1) != EOK) { 828fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc strncpy_s failed"; 829fb299fa2Sopenharmony_ci return; 830fb299fa2Sopenharmony_ci } 831fb299fa2Sopenharmony_ci (void)memset_s(msg.update, sizeof(msg.update), 0, sizeof(msg.update)); 832fb299fa2Sopenharmony_ci for (const auto& arg : args) { 833fb299fa2Sopenharmony_ci if (arg.find(headInfo) == std::string::npos) { 834fb299fa2Sopenharmony_ci if (strncat_s(msg.update, sizeof(msg.update), arg.c_str(), strlen(arg.c_str()) + 1) != EOK) { 835fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc strncat_s failed"; 836fb299fa2Sopenharmony_ci return; 837fb299fa2Sopenharmony_ci } 838fb299fa2Sopenharmony_ci if (strncat_s(msg.update, sizeof(msg.update), "\n", strlen("\n") + 1) != EOK) { 839fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc strncat_s failed"; 840fb299fa2Sopenharmony_ci return; 841fb299fa2Sopenharmony_ci } 842fb299fa2Sopenharmony_ci } 843fb299fa2Sopenharmony_ci } 844fb299fa2Sopenharmony_ci char buffer[128] {}; // 128 : set headInfo size 845fb299fa2Sopenharmony_ci if (headInfo == "sdcard_update") { 846fb299fa2Sopenharmony_ci if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s", headInfo.c_str()) == -1) { 847fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc snprintf_s failed"; 848fb299fa2Sopenharmony_ci return; 849fb299fa2Sopenharmony_ci } 850fb299fa2Sopenharmony_ci } else { 851fb299fa2Sopenharmony_ci if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s=%d", headInfo.c_str(), message) == -1) { 852fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc snprintf_s failed"; 853fb299fa2Sopenharmony_ci return; 854fb299fa2Sopenharmony_ci } 855fb299fa2Sopenharmony_ci } 856fb299fa2Sopenharmony_ci if (strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1) != EOK) { 857fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc strncat_s failed"; 858fb299fa2Sopenharmony_ci return; 859fb299fa2Sopenharmony_ci } 860fb299fa2Sopenharmony_ci if (WriteUpdaterMiscMsg(msg) != true) { 861fb299fa2Sopenharmony_ci LOG(ERROR) << "Write command to misc failed."; 862fb299fa2Sopenharmony_ci } 863fb299fa2Sopenharmony_ci} 864fb299fa2Sopenharmony_ci 865fb299fa2Sopenharmony_civoid SetCmdToMisc(const std::string &miscCmd) 866fb299fa2Sopenharmony_ci{ 867fb299fa2Sopenharmony_ci struct UpdateMessage msg {}; 868fb299fa2Sopenharmony_ci if (!ReadUpdaterMiscMsg(msg)) { 869fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc read misc failed"; 870fb299fa2Sopenharmony_ci return; 871fb299fa2Sopenharmony_ci } 872fb299fa2Sopenharmony_ci 873fb299fa2Sopenharmony_ci (void)memset_s(msg.command, sizeof(msg.command), 0, sizeof(msg.command)); 874fb299fa2Sopenharmony_ci if (strncpy_s(msg.command, sizeof(msg.command), miscCmd.c_str(), miscCmd.size() + 1) != EOK) { 875fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc strncpy_s failed"; 876fb299fa2Sopenharmony_ci return; 877fb299fa2Sopenharmony_ci } 878fb299fa2Sopenharmony_ci 879fb299fa2Sopenharmony_ci if (WriteUpdaterMiscMsg(msg) != true) { 880fb299fa2Sopenharmony_ci LOG(ERROR) << "Write command to misc failed."; 881fb299fa2Sopenharmony_ci } 882fb299fa2Sopenharmony_ci} 883fb299fa2Sopenharmony_ci 884fb299fa2Sopenharmony_civoid AddUpdateInfoToMisc(const std::string headInfo, const std::optional<int> message) 885fb299fa2Sopenharmony_ci{ 886fb299fa2Sopenharmony_ci UpdateInfoInMisc(headInfo, message, false); 887fb299fa2Sopenharmony_ci} 888fb299fa2Sopenharmony_ci 889fb299fa2Sopenharmony_civoid RemoveUpdateInfoFromMisc(const std::string &headInfo) 890fb299fa2Sopenharmony_ci{ 891fb299fa2Sopenharmony_ci UpdateInfoInMisc(headInfo, std::nullopt, true); 892fb299fa2Sopenharmony_ci} 893fb299fa2Sopenharmony_ci 894fb299fa2Sopenharmony_civoid SetFaultInfoToMisc(const std::string &faultInfo) 895fb299fa2Sopenharmony_ci{ 896fb299fa2Sopenharmony_ci struct UpdateMessage msg {}; 897fb299fa2Sopenharmony_ci if (!ReadUpdaterMiscMsg(msg)) { 898fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc read misc failed"; 899fb299fa2Sopenharmony_ci return; 900fb299fa2Sopenharmony_ci } 901fb299fa2Sopenharmony_ci 902fb299fa2Sopenharmony_ci (void)memset_s(msg.faultinfo, sizeof(msg.faultinfo), 0, sizeof(msg.faultinfo)); 903fb299fa2Sopenharmony_ci if (strncpy_s(msg.faultinfo, sizeof(msg.faultinfo), faultInfo.c_str(), faultInfo.size() + 1) != EOK) { 904fb299fa2Sopenharmony_ci LOG(ERROR) << "SetMessageToMisc strncpy_s failed"; 905fb299fa2Sopenharmony_ci return; 906fb299fa2Sopenharmony_ci } 907fb299fa2Sopenharmony_ci 908fb299fa2Sopenharmony_ci if (WriteUpdaterMiscMsg(msg) != true) { 909fb299fa2Sopenharmony_ci LOG(ERROR) << "Write fault info to misc failed."; 910fb299fa2Sopenharmony_ci } 911fb299fa2Sopenharmony_ci} 912fb299fa2Sopenharmony_ci 913fb299fa2Sopenharmony_cibool CheckFaultInfo(const std::string &faultInfo) 914fb299fa2Sopenharmony_ci{ 915fb299fa2Sopenharmony_ci struct UpdateMessage msg = {}; 916fb299fa2Sopenharmony_ci if (!ReadUpdaterMiscMsg(msg)) { 917fb299fa2Sopenharmony_ci LOG(ERROR) << "read misc data failed"; 918fb299fa2Sopenharmony_ci return false; 919fb299fa2Sopenharmony_ci } 920fb299fa2Sopenharmony_ci 921fb299fa2Sopenharmony_ci if (strcmp(msg.faultinfo, faultInfo.c_str()) == 0) { 922fb299fa2Sopenharmony_ci return true; 923fb299fa2Sopenharmony_ci } 924fb299fa2Sopenharmony_ci return false; 925fb299fa2Sopenharmony_ci} 926fb299fa2Sopenharmony_ci 927fb299fa2Sopenharmony_civoid GetTagValInStr(const std::string &str, const std::string &tag, std::string &val) 928fb299fa2Sopenharmony_ci{ 929fb299fa2Sopenharmony_ci if (str.find(tag + "=") != std::string::npos) { 930fb299fa2Sopenharmony_ci val = str.substr(str.find("=") + 1, str.size() - str.find("=")); 931fb299fa2Sopenharmony_ci } 932fb299fa2Sopenharmony_ci} 933fb299fa2Sopenharmony_ci 934fb299fa2Sopenharmony_cibool IsValidHexStr(const std::string &str) 935fb299fa2Sopenharmony_ci{ 936fb299fa2Sopenharmony_ci for (const auto &ch : str) { 937fb299fa2Sopenharmony_ci if (isxdigit(ch) == 0) { 938fb299fa2Sopenharmony_ci return false; 939fb299fa2Sopenharmony_ci } 940fb299fa2Sopenharmony_ci } 941fb299fa2Sopenharmony_ci return true; 942fb299fa2Sopenharmony_ci} 943fb299fa2Sopenharmony_ci 944fb299fa2Sopenharmony_civoid TrimString(std::string &str) 945fb299fa2Sopenharmony_ci{ 946fb299fa2Sopenharmony_ci auto pos = str.find_last_not_of("\r\n"); 947fb299fa2Sopenharmony_ci if (pos != std::string::npos) { 948fb299fa2Sopenharmony_ci str.erase(pos + 1, str.size() - pos); 949fb299fa2Sopenharmony_ci } 950fb299fa2Sopenharmony_ci} 951fb299fa2Sopenharmony_ci 952fb299fa2Sopenharmony_cibool IsEsDevice() 953fb299fa2Sopenharmony_ci{ 954fb299fa2Sopenharmony_ci char deviceType[PARAM_SIZE + 1] = {0}; 955fb299fa2Sopenharmony_ci if (GetParameter("ohos.boot.chiptype", "", deviceType, sizeof(deviceType) - 1) <= 0) { 956fb299fa2Sopenharmony_ci LOG(ERROR) << "get device type failed"; 957fb299fa2Sopenharmony_ci return false; 958fb299fa2Sopenharmony_ci } 959fb299fa2Sopenharmony_ci LOG(INFO) << "device type is " << deviceType; 960fb299fa2Sopenharmony_ci if (strstr(deviceType, "_es") == nullptr) { 961fb299fa2Sopenharmony_ci return false; 962fb299fa2Sopenharmony_ci } 963fb299fa2Sopenharmony_ci return true; 964fb299fa2Sopenharmony_ci} 965fb299fa2Sopenharmony_ci 966fb299fa2Sopenharmony_ci#ifndef __WIN32 967fb299fa2Sopenharmony_civoid SetFileAttributes(const std::string& file, uid_t owner, gid_t group, mode_t mode) 968fb299fa2Sopenharmony_ci{ 969fb299fa2Sopenharmony_ci#ifdef WITH_SELINUX 970fb299fa2Sopenharmony_ci RestoreconRecurse(file.c_str()); 971fb299fa2Sopenharmony_ci#endif // WITH_SELINUX 972fb299fa2Sopenharmony_ci if (chown(file.c_str(), USER_ROOT_AUTHORITY, GROUP_ROOT_AUTHORITY) != 0) { 973fb299fa2Sopenharmony_ci LOG(ERROR) << "Chown failed: " << file << " " << USER_ROOT_AUTHORITY << "," << GROUP_ROOT_AUTHORITY; 974fb299fa2Sopenharmony_ci } 975fb299fa2Sopenharmony_ci if (chmod(file.c_str(), mode) != EOK) { 976fb299fa2Sopenharmony_ci LOG(ERROR) << "chmod failed: " << file << " " << mode; 977fb299fa2Sopenharmony_ci } 978fb299fa2Sopenharmony_ci if (chown(file.c_str(), owner, group) != 0) { 979fb299fa2Sopenharmony_ci LOG(ERROR) << "Chown failed: " << file << " " << owner << "," << group; 980fb299fa2Sopenharmony_ci } 981fb299fa2Sopenharmony_ci} 982fb299fa2Sopenharmony_ci#endif 983fb299fa2Sopenharmony_ci} // Utils 984fb299fa2Sopenharmony_civoid __attribute__((weak)) InitLogger(const std::string &tag) 985fb299fa2Sopenharmony_ci{ 986fb299fa2Sopenharmony_ci if (Utils::IsUpdaterMode()) { 987fb299fa2Sopenharmony_ci InitUpdaterLogger(tag, TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); 988fb299fa2Sopenharmony_ci } else { 989fb299fa2Sopenharmony_ci InitUpdaterLogger(tag, SYS_INSTALLER_LOG, UPDATER_STAGE_LOG, ERROR_CODE_PATH); 990fb299fa2Sopenharmony_ci } 991fb299fa2Sopenharmony_ci} 992fb299fa2Sopenharmony_ci} // namespace Updater 993