1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2021-2023 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 <chrono> 16fb299fa2Sopenharmony_ci#include <dirent.h> 17fb299fa2Sopenharmony_ci#include <fcntl.h> 18fb299fa2Sopenharmony_ci#include <sys/mount.h> 19fb299fa2Sopenharmony_ci#include <sys/stat.h> 20fb299fa2Sopenharmony_ci#include <sys/statvfs.h> 21fb299fa2Sopenharmony_ci#include <regex> 22fb299fa2Sopenharmony_ci 23fb299fa2Sopenharmony_ci#include "applypatch/partition_record.h" 24fb299fa2Sopenharmony_ci#include "flashd/flashd.h" 25fb299fa2Sopenharmony_ci#include "log/log.h" 26fb299fa2Sopenharmony_ci#include "misc_info/misc_info.h" 27fb299fa2Sopenharmony_ci#include "package/pkg_manager.h" 28fb299fa2Sopenharmony_ci#include "securec.h" 29fb299fa2Sopenharmony_ci#include "updater/updater.h" 30fb299fa2Sopenharmony_ci#include "updater/updater_const.h" 31fb299fa2Sopenharmony_ci#include "updater_main.h" 32fb299fa2Sopenharmony_ci#include "utils.h" 33fb299fa2Sopenharmony_ci 34fb299fa2Sopenharmony_cinamespace Updater { 35fb299fa2Sopenharmony_ciusing namespace Hpackage; 36fb299fa2Sopenharmony_ciusing namespace Updater::Utils; 37fb299fa2Sopenharmony_ci 38fb299fa2Sopenharmony_civoid DeleteInstallTimeFile() 39fb299fa2Sopenharmony_ci{ 40fb299fa2Sopenharmony_ci const std::string installTimeFilePath = std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE); 41fb299fa2Sopenharmony_ci if (access(installTimeFilePath.c_str(), F_OK) != -1) { 42fb299fa2Sopenharmony_ci (void)DeleteFile(installTimeFilePath); 43fb299fa2Sopenharmony_ci LOG(INFO) << "delete install time file"; 44fb299fa2Sopenharmony_ci } 45fb299fa2Sopenharmony_ci} 46fb299fa2Sopenharmony_ci 47fb299fa2Sopenharmony_cibool IsDouble(const std::string& str) 48fb299fa2Sopenharmony_ci{ 49fb299fa2Sopenharmony_ci std::regex pattern("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$"); 50fb299fa2Sopenharmony_ci return std::regex_match(str, pattern); 51fb299fa2Sopenharmony_ci} 52fb299fa2Sopenharmony_ci 53fb299fa2Sopenharmony_civoid WriteInstallTime(UpdaterParams &upParams) 54fb299fa2Sopenharmony_ci{ 55fb299fa2Sopenharmony_ci std::ofstream ofs; 56fb299fa2Sopenharmony_ci ofs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::app | std::ios::out); 57fb299fa2Sopenharmony_ci if (!ofs.is_open()) { 58fb299fa2Sopenharmony_ci LOG(ERROR) << "open install time file fail"; 59fb299fa2Sopenharmony_ci return; 60fb299fa2Sopenharmony_ci } 61fb299fa2Sopenharmony_ci ofs << DurationToString(upParams.installTime, upParams.pkgLocation) << "\n"; 62fb299fa2Sopenharmony_ci} 63fb299fa2Sopenharmony_ci 64fb299fa2Sopenharmony_civoid ReadInstallTime(UpdaterParams &upParams) 65fb299fa2Sopenharmony_ci{ 66fb299fa2Sopenharmony_ci std::ifstream ifs; 67fb299fa2Sopenharmony_ci std::string buf; 68fb299fa2Sopenharmony_ci ifs.open(std::string(UPDATER_PATH) + "/" + std::string(INSTALL_TIME_FILE), std::ios::in); 69fb299fa2Sopenharmony_ci if (!ifs.is_open()) { 70fb299fa2Sopenharmony_ci LOG(ERROR) << "read install time file fail"; 71fb299fa2Sopenharmony_ci return; 72fb299fa2Sopenharmony_ci } 73fb299fa2Sopenharmony_ci unsigned int index = 0; 74fb299fa2Sopenharmony_ci while (getline(ifs, buf)) { 75fb299fa2Sopenharmony_ci if (index >= upParams.pkgLocation) { 76fb299fa2Sopenharmony_ci break; 77fb299fa2Sopenharmony_ci } 78fb299fa2Sopenharmony_ci if (IsDouble(buf)) { 79fb299fa2Sopenharmony_ci upParams.installTime[index++] = std::chrono::duration<double>(std::stod(buf)); 80fb299fa2Sopenharmony_ci } else { 81fb299fa2Sopenharmony_ci LOG(ERROR) << "read install time is invalid"; 82fb299fa2Sopenharmony_ci } 83fb299fa2Sopenharmony_ci } 84fb299fa2Sopenharmony_ci} 85fb299fa2Sopenharmony_ci 86fb299fa2Sopenharmony_cibool DeleteUpdaterPath(const std::string &path) 87fb299fa2Sopenharmony_ci{ 88fb299fa2Sopenharmony_ci auto pDir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(path.c_str()), closedir); 89fb299fa2Sopenharmony_ci if (pDir == nullptr) { 90fb299fa2Sopenharmony_ci LOG(INFO) << "Can not open dir"; 91fb299fa2Sopenharmony_ci return true; 92fb299fa2Sopenharmony_ci } 93fb299fa2Sopenharmony_ci bool sdcardTmp = false; 94fb299fa2Sopenharmony_ci if (path.find("sdcard") != std::string::npos) { 95fb299fa2Sopenharmony_ci sdcardTmp = true; 96fb299fa2Sopenharmony_ci } 97fb299fa2Sopenharmony_ci struct dirent *dp = nullptr; 98fb299fa2Sopenharmony_ci while ((dp = readdir(pDir.get())) != nullptr) { 99fb299fa2Sopenharmony_ci std::string currentName(dp->d_name); 100fb299fa2Sopenharmony_ci if (currentName[0] == '.' || (currentName.compare("log") == 0) || 101fb299fa2Sopenharmony_ci (currentName.compare(UPDATER_RESULT_FILE) == 0) || 102fb299fa2Sopenharmony_ci (currentName.compare(UPDATER_LOCALE_FILE) == 0) || 103fb299fa2Sopenharmony_ci (currentName.compare(MODULE_UPDATE_RESULT_FILE) == 0) || 104fb299fa2Sopenharmony_ci (currentName.compare(UPLOAD_LOG_TIME_FILE) == 0)) { 105fb299fa2Sopenharmony_ci continue; 106fb299fa2Sopenharmony_ci } 107fb299fa2Sopenharmony_ci if (sdcardTmp && currentName.find(SDCARD_PACKAGE_SUFFIX) != std::string::npos) { 108fb299fa2Sopenharmony_ci continue; 109fb299fa2Sopenharmony_ci } 110fb299fa2Sopenharmony_ci std::string tmpName(path); 111fb299fa2Sopenharmony_ci tmpName.append("/" + currentName); 112fb299fa2Sopenharmony_ci if (IsDirExist(tmpName)) { 113fb299fa2Sopenharmony_ci DeleteUpdaterPath(tmpName); 114fb299fa2Sopenharmony_ci } 115fb299fa2Sopenharmony_ci#ifndef UPDATER_UT 116fb299fa2Sopenharmony_ci remove(tmpName.c_str()); 117fb299fa2Sopenharmony_ci#endif 118fb299fa2Sopenharmony_ci } 119fb299fa2Sopenharmony_ci return true; 120fb299fa2Sopenharmony_ci} 121fb299fa2Sopenharmony_ci 122fb299fa2Sopenharmony_cibool ClearMisc() 123fb299fa2Sopenharmony_ci{ 124fb299fa2Sopenharmony_ci struct UpdateMessage cleanBoot {}; 125fb299fa2Sopenharmony_ci if (!WriteUpdaterMiscMsg(cleanBoot)) { 126fb299fa2Sopenharmony_ci LOG(ERROR) << "ClearMisc clear boot message to misc failed"; 127fb299fa2Sopenharmony_ci return false; 128fb299fa2Sopenharmony_ci } 129fb299fa2Sopenharmony_ci auto miscBlockDev = GetBlockDeviceByMountPoint(MISC_PATH); 130fb299fa2Sopenharmony_ci if (miscBlockDev.empty()) { 131fb299fa2Sopenharmony_ci LOG(INFO) << "cannot get block device of partition"; 132fb299fa2Sopenharmony_ci miscBlockDev = MISC_FILE; 133fb299fa2Sopenharmony_ci } 134fb299fa2Sopenharmony_ci LOG(INFO) << "ClearMisc::misc path : " << miscBlockDev; 135fb299fa2Sopenharmony_ci auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(miscBlockDev.c_str(), "rb+"), fclose); 136fb299fa2Sopenharmony_ci if (fp == nullptr) { 137fb299fa2Sopenharmony_ci LOG(ERROR) << "WriteVersionCode fopen failed" << " : " << strerror(errno); 138fb299fa2Sopenharmony_ci return false; 139fb299fa2Sopenharmony_ci } 140fb299fa2Sopenharmony_ci if (fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET) != 0) { 141fb299fa2Sopenharmony_ci LOG(ERROR) << "ClearMisc fseek failed"; 142fb299fa2Sopenharmony_ci return false; 143fb299fa2Sopenharmony_ci } 144fb299fa2Sopenharmony_ci off_t clearOffset = 0; 145fb299fa2Sopenharmony_ci if (fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) != 1) { 146fb299fa2Sopenharmony_ci LOG(ERROR) << "ClearMisc write misc initOffset 0 failed" << " : " << strerror(errno); 147fb299fa2Sopenharmony_ci return false; 148fb299fa2Sopenharmony_ci } 149fb299fa2Sopenharmony_ci 150fb299fa2Sopenharmony_ci struct PartitionRecordInfo cleanPartition {}; 151fb299fa2Sopenharmony_ci for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset += 152fb299fa2Sopenharmony_ci sizeof(PartitionRecordInfo)) { 153fb299fa2Sopenharmony_ci if (fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET) != 0) { 154fb299fa2Sopenharmony_ci LOG(ERROR) << "ClearMisc fseek failed"; 155fb299fa2Sopenharmony_ci return false; 156fb299fa2Sopenharmony_ci } 157fb299fa2Sopenharmony_ci if (fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) != 1) { 158fb299fa2Sopenharmony_ci LOG(ERROR) << "ClearMisc write misc cleanPartition failed" << " : " << strerror(errno); 159fb299fa2Sopenharmony_ci return false; 160fb299fa2Sopenharmony_ci } 161fb299fa2Sopenharmony_ci } 162fb299fa2Sopenharmony_ci return true; 163fb299fa2Sopenharmony_ci} 164fb299fa2Sopenharmony_ci 165fb299fa2Sopenharmony_cibool IsSDCardExist(const std::string &sdcardPath) 166fb299fa2Sopenharmony_ci{ 167fb299fa2Sopenharmony_ci // Record system error codes. 168fb299fa2Sopenharmony_ci int save_errno = errno; 169fb299fa2Sopenharmony_ci struct stat st {}; 170fb299fa2Sopenharmony_ci if (stat(sdcardPath.c_str(), &st) < 0) { 171fb299fa2Sopenharmony_ci return false; 172fb299fa2Sopenharmony_ci } else { 173fb299fa2Sopenharmony_ci errno = save_errno; 174fb299fa2Sopenharmony_ci return true; 175fb299fa2Sopenharmony_ci } 176fb299fa2Sopenharmony_ci} 177fb299fa2Sopenharmony_ci 178fb299fa2Sopenharmony_civoid PostUpdater(bool clearMisc) 179fb299fa2Sopenharmony_ci{ 180fb299fa2Sopenharmony_ci STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater"; 181fb299fa2Sopenharmony_ci 182fb299fa2Sopenharmony_ci if (!CheckUpdateMode(SDCARD_MODE) && !CheckUpdateMode(USB_MODE) && (CheckUpdateMode(OTA_MODE) || 183fb299fa2Sopenharmony_ci GetMountStatusForMountPoint("/log") != MountStatus::MOUNT_MOUNTED)) { 184fb299fa2Sopenharmony_ci (void)SetupPartitions(); 185fb299fa2Sopenharmony_ci } else { 186fb299fa2Sopenharmony_ci (void)SetupPartitions(false); 187fb299fa2Sopenharmony_ci } 188fb299fa2Sopenharmony_ci UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_INIT_EVENT); 189fb299fa2Sopenharmony_ci // clear update misc partition. 190fb299fa2Sopenharmony_ci if (clearMisc && !ClearMisc()) { 191fb299fa2Sopenharmony_ci LOG(ERROR) << "PostUpdater clear misc failed"; 192fb299fa2Sopenharmony_ci } 193fb299fa2Sopenharmony_ci if (!access(COMMAND_FILE, 0) && unlink(COMMAND_FILE) != 0) { 194fb299fa2Sopenharmony_ci LOG(ERROR) << "Delete command failed"; 195fb299fa2Sopenharmony_ci } 196fb299fa2Sopenharmony_ci 197fb299fa2Sopenharmony_ci // delete updater tmp files 198fb299fa2Sopenharmony_ci if (access(UPDATER_PATH, 0) == 0 && access(SDCARD_CARD_PATH, 0) != 0 && !DeleteUpdaterPath(UPDATER_PATH)) { 199fb299fa2Sopenharmony_ci LOG(ERROR) << "DeleteUpdaterPath failed"; 200fb299fa2Sopenharmony_ci } 201fb299fa2Sopenharmony_ci if (access(SDCARD_CARD_PATH, 0) == 0 && !DeleteUpdaterPath(SDCARD_CARD_PATH)) { 202fb299fa2Sopenharmony_ci LOG(ERROR) << "Delete sdcard path failed"; 203fb299fa2Sopenharmony_ci } 204fb299fa2Sopenharmony_ci if (access(Flashd::FLASHD_FILE_PATH, 0) == 0 && !DeleteUpdaterPath(Flashd::FLASHD_FILE_PATH)) { 205fb299fa2Sopenharmony_ci LOG(ERROR) << "DeleteUpdaterPath failed"; 206fb299fa2Sopenharmony_ci } 207fb299fa2Sopenharmony_ci if (!CheckUpdateMode(SDCARD_MODE) && !CheckUpdateMode(USB_MODE) && 208fb299fa2Sopenharmony_ci GetMountStatusForMountPoint("/log") != MountStatus::MOUNT_MOUNTED) { 209fb299fa2Sopenharmony_ci SaveLogs(); 210fb299fa2Sopenharmony_ci } 211fb299fa2Sopenharmony_ci} 212fb299fa2Sopenharmony_ci 213fb299fa2Sopenharmony_civoid BootMode::InitMode(void) const 214fb299fa2Sopenharmony_ci{ 215fb299fa2Sopenharmony_ci InitLogger(modeName); 216fb299fa2Sopenharmony_ci#ifdef UPDATER_BUILD_VARIANT_USER 217fb299fa2Sopenharmony_ci SetLogLevel(INFO); 218fb299fa2Sopenharmony_ci#else 219fb299fa2Sopenharmony_ci SetLogLevel(DEBUG); 220fb299fa2Sopenharmony_ci#endif 221fb299fa2Sopenharmony_ci LoadFstab(); 222fb299fa2Sopenharmony_ci STAGE(UPDATE_STAGE_OUT) << "Start " << modeName; 223fb299fa2Sopenharmony_ci SetParameter(modePara.c_str(), "1"); 224fb299fa2Sopenharmony_ci} 225fb299fa2Sopenharmony_ci 226fb299fa2Sopenharmony_cibool IsUpdater(const UpdateMessage &boot) 227fb299fa2Sopenharmony_ci{ 228fb299fa2Sopenharmony_ci return !IsFlashd(boot) && strncmp(boot.command, "boot_updater", sizeof("boot_updater") - 1) == 0; 229fb299fa2Sopenharmony_ci} 230fb299fa2Sopenharmony_ci 231fb299fa2Sopenharmony_cibool IsFlashd(const UpdateMessage &boot) 232fb299fa2Sopenharmony_ci{ 233fb299fa2Sopenharmony_ci return strncmp(boot.update, "boot_flash", sizeof("boot_flash") - 1) == 0; 234fb299fa2Sopenharmony_ci} 235fb299fa2Sopenharmony_ci 236fb299fa2Sopenharmony_cistd::vector<BootMode> &GetBootModes(void) 237fb299fa2Sopenharmony_ci{ 238fb299fa2Sopenharmony_ci static std::vector<BootMode> bootModes {}; 239fb299fa2Sopenharmony_ci return bootModes; 240fb299fa2Sopenharmony_ci} 241fb299fa2Sopenharmony_ci 242fb299fa2Sopenharmony_civoid RegisterMode(const BootMode &mode) 243fb299fa2Sopenharmony_ci{ 244fb299fa2Sopenharmony_ci GetBootModes().push_back(mode); 245fb299fa2Sopenharmony_ci} 246fb299fa2Sopenharmony_ci 247fb299fa2Sopenharmony_cistd::optional<BootMode> SelectMode(const UpdateMessage &boot) 248fb299fa2Sopenharmony_ci{ 249fb299fa2Sopenharmony_ci const auto &modes = GetBootModes(); 250fb299fa2Sopenharmony_ci 251fb299fa2Sopenharmony_ci // select modes by bootMode.cond which would check misc message 252fb299fa2Sopenharmony_ci auto it = std::find_if(modes.begin(), modes.end(), [&boot] (const auto &bootMode) { 253fb299fa2Sopenharmony_ci if (bootMode.cond != nullptr && bootMode.cond(boot)) { 254fb299fa2Sopenharmony_ci LOG(INFO) << "condition for mode " << bootMode.modeName << " is satisfied"; 255fb299fa2Sopenharmony_ci return true; 256fb299fa2Sopenharmony_ci } 257fb299fa2Sopenharmony_ci LOG(WARNING) << "condition for mode " << bootMode.modeName << " is not satisfied"; 258fb299fa2Sopenharmony_ci return false; 259fb299fa2Sopenharmony_ci }); 260fb299fa2Sopenharmony_ci // misc check failed for each mode, then enter updater mode 261fb299fa2Sopenharmony_ci if (it == modes.end() || it->entryFunc == nullptr) { 262fb299fa2Sopenharmony_ci LOG(WARNING) << "find valid mode failed, enter updater Mode"; 263fb299fa2Sopenharmony_ci return std::nullopt; 264fb299fa2Sopenharmony_ci } 265fb299fa2Sopenharmony_ci 266fb299fa2Sopenharmony_ci LOG(INFO) << "enter " << it->modeName << " mode"; 267fb299fa2Sopenharmony_ci return *it; 268fb299fa2Sopenharmony_ci} 269fb299fa2Sopenharmony_ci} // namespace Updater 270