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