• 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 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