• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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