1/* 2 * Copyright (c) 2021 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 "updaterkits/updaterkits.h" 16 17#include <string> 18#include <sys/stat.h> 19#include <unistd.h> 20#include "init_reboot.h" 21#include "log.h" 22#include "misc_info/misc_info.h" 23#include "securec.h" 24#include "updater/updater_const.h" 25#include "utils.h" 26#include "utils_fs.h" 27 28using namespace Updater; 29using Updater::Utils::SplitString; 30 31static bool WriteToMiscAndRebootToUpdater(const struct UpdateMessage &updateMsg) 32{ 33 // Write package name to misc, then trigger reboot. 34 const char *bootCmd = "boot_updater"; 35 int ret = strncpy_s(const_cast<char*>(updateMsg.command), sizeof(updateMsg.command), bootCmd, 36 sizeof(updateMsg.command) - 1); 37 if (ret != 0) { 38 return false; 39 } 40#ifndef UPDATER_UT 41 WriteUpdaterMiscMsg(updateMsg); 42 DoReboot("updater:reboot to updater to trigger update"); 43 while (true) { 44 pause(); 45 } 46#else 47 return true; 48#endif 49} 50 51static void WriteUpdaterResultFile(const std::string &pkgPath, const std::string &result) 52{ 53 if (access(UPDATER_PATH, 0) != 0) { 54 if (Utils::MkdirRecursive(UPDATER_PATH, 0755) != 0) { // 0755: -rwxr-xr-x 55 LOG(ERROR) << "Mkdir recursive error!"; 56 return; 57 } 58 } 59 LOG(INFO) << "WriteUpdaterResultFile: " << result; 60 const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE); 61 FILE *fp = fopen(resultPath.c_str(), "w+"); 62 if (fp == nullptr) { 63 LOG(ERROR) << "open updater result file failed"; 64 return; 65 } 66 std::string resultInfo = pkgPath + "|fail|" + result + "||\n"; 67 if (fwrite(resultInfo.c_str(), resultInfo.size() + 1, 1, fp) <= 0) { 68 LOG(WARNING) << "write updater result file failed, err:" << errno; 69 } 70 if (fsync(fileno(fp)) != 0) { 71 LOG(WARNING) << "WriteUpdaterResultFile fsync failed" << strerror(errno); 72 } 73 if (fclose(fp) != 0) { 74 LOG(WARNING) << "close updater result file failed"; 75 } 76 77 (void)chown(resultPath.c_str(), Utils::USER_ROOT_AUTHORITY, Utils::GROUP_UPDATE_AUTHORITY); 78 (void)chmod(resultPath.c_str(), 0660); // 0660: -rw-rw---- 79} 80 81static std::string ParsePkgPath(const struct UpdateMessage &updateMsg) 82{ 83 std::string pkgPath = ""; 84 std::string pathInfo(updateMsg.update, sizeof(updateMsg.update)); 85 std::string::size_type startPos = pathInfo.find("update_package="); 86 std::string::size_type endPos = pathInfo.find(".zip"); 87 if (startPos != pathInfo.npos && endPos != pathInfo.npos) { 88 startPos += strlen("update_package="); 89 endPos += strlen(".zip"); 90 if (endPos > startPos) { 91 pkgPath = pathInfo.substr(startPos, endPos - startPos); 92 } else { 93 LOG(ERROR) << "pkgPath invalid"; 94 } 95 } 96 return pkgPath; 97} 98 99static bool WriteToMiscAndResultFileRebootToUpdater(const struct UpdateMessage &updateMsg) 100{ 101 // Write package name to misc, then trigger reboot. 102 const char *bootCmd = "boot_updater"; 103 int ret = strncpy_s(const_cast<char*>(updateMsg.command), sizeof(updateMsg.command), bootCmd, 104 sizeof(updateMsg.command) - 1); 105 if (ret != 0) { 106 return false; 107 } 108 std::string pkgPath = ParsePkgPath(updateMsg); 109 // Flag before the misc in written 110 std::string writeMiscBefore = "0x80000000"; 111 WriteUpdaterResultFile(pkgPath, writeMiscBefore); 112#ifndef UPDATER_UT 113 WriteUpdaterMiscMsg(updateMsg); 114 // Flag after the misc in written 115 std::string writeMiscAfter = "0x80000008"; 116 WriteUpdaterResultFile(pkgPath, writeMiscAfter); 117 DoReboot("updater:reboot to updater to trigger update"); 118 while (true) { 119 pause(); 120 } 121#else 122 return true; 123#endif 124} 125 126static bool IsPackagePath(const std::string &path) 127{ 128 if (path.find("--force_update_action=") != std::string::npos || 129 path.find("--night_update") != std::string::npos) { 130 return false; 131 } 132 return true; 133} 134 135static int AddPkgPath(struct UpdateMessage &msg, size_t updateOffset, const std::vector<std::string> &packageName) 136{ 137 for (auto path : packageName) { 138 if (updateOffset > sizeof(msg.update)) { 139 LOG(ERROR) << "updaterkits: updateOffset > msg.update, return false"; 140 return 4; // 4 : path is too long 141 } 142 int ret; 143 if (IsPackagePath(path)) { 144 ret = snprintf_s(msg.update + updateOffset, sizeof(msg.update) - updateOffset, 145 sizeof(msg.update) - 1 - updateOffset, "--update_package=%s\n", path.c_str()); 146 } else { 147 ret = snprintf_s(msg.update + updateOffset, sizeof(msg.update) - updateOffset, 148 sizeof(msg.update) - 1 - updateOffset, "%s\n", path.c_str()); 149 } 150 if (ret < 0) { 151 LOG(ERROR) << "updaterkits: copy updater message failed"; 152 return 5; // 5 : The library function is incorrect 153 } 154 updateOffset += static_cast<size_t>(ret); 155 } 156 return 0; 157} 158 159bool RebootAndInstallSdcardPackage(const std::string &miscFile, const std::vector<std::string> &packageName) 160{ 161 struct UpdateMessage msg {}; 162 int ret = snprintf_s(msg.update, sizeof(msg.update), sizeof(msg.update) - 1, "--sdcard_update\n"); 163 if (ret < 0) { 164 LOG(ERROR) << "updaterkits: copy updater message failed"; 165 return false; 166 } 167 168 if (packageName.size() != 0 && AddPkgPath(msg, static_cast<size_t>(ret), packageName) != 0) { 169 LOG(ERROR) << "get sdcard pkg path fail"; 170 return false; 171 } 172 WriteToMiscAndRebootToUpdater(msg); 173 174 // Never get here. 175 return true; 176} 177 178int RebootAndInstallUpgradePackage(const std::string &miscFile, const std::vector<std::string> &packageName, 179 const std::string &upgradeType) 180{ 181 if (packageName.size() == 0 && upgradeType == UPGRADE_TYPE_OTA) { 182 LOG(ERROR) << "updaterkits: invalid argument. one of arugments is empty"; 183 return 1; // 1 : Invalid input 184 } 185 186 for (auto path : packageName) { 187 if (IsPackagePath(path)) { 188 if (access(path.c_str(), R_OK) < 0) { 189 LOG(ERROR) << "updaterkits: " << path << " is not readable"; 190 return 2; // 2 : pkg not exit 191 } 192 } 193 } 194 struct UpdateMessage updateMsg {}; 195 int ret = 0; 196 if (upgradeType == UPGRADE_TYPE_SD) { 197 ret = snprintf_s(updateMsg.update, sizeof(updateMsg.update), sizeof(updateMsg.update) - 1, 198 "--sdcard_update\n"); 199 } else if (upgradeType == UPGRADE_TYPE_SD_INTRAL) { 200 ret = snprintf_s(updateMsg.update, sizeof(updateMsg.update), sizeof(updateMsg.update) - 1, 201 "--sdcard_intral_update\n"); 202 } 203 if (ret < 0) { 204 LOG(ERROR) << "updaterkits: copy updater message failed"; 205 return 3; // 3 : The library function is incorrect 206 } 207 int addRet = AddPkgPath(updateMsg, static_cast<size_t>(ret), packageName); 208 if (addRet != 0) { 209 return addRet; 210 } 211 if (upgradeType == UPGRADE_TYPE_OTA) { 212 WriteToMiscAndResultFileRebootToUpdater(updateMsg); 213 } else { 214 WriteToMiscAndRebootToUpdater(updateMsg); 215 } 216 217 // Never get here. 218 return 0; 219} 220 221bool RebootAndCleanUserData(const std::string &miscFile, const std::string &cmd) 222{ 223 if (miscFile.empty() || cmd.empty()) { 224 LOG(ERROR) << "updaterkits: invalid argument. one of arugments is empty"; 225 return false; 226 } 227 228 // Write package name to misc, then trigger reboot. 229 struct UpdateMessage updateMsg {}; 230 if (strncpy_s(updateMsg.update, sizeof(updateMsg.update), cmd.c_str(), cmd.size()) != EOK) { 231 LOG(ERROR) << "updaterkits: copy updater message failed"; 232 return false; 233 } 234 235 WriteToMiscAndRebootToUpdater(updateMsg); 236 237 // Never get here. 238 return true; 239} 240