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