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