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 
28 using namespace Updater;
29 using Updater::Utils::SplitString;
30 
WriteToMiscAndRebootToUpdater(const struct UpdateMessage & updateMsg)31 static 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");
43     while (true) {
44         pause();
45     }
46 #else
47     return true;
48 #endif
49 }
50 
WriteUpdaterResultFile(const std::string & pkgPath,const std::string & result)51 static 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 
ParsePkgPath(const struct UpdateMessage & updateMsg)81 static 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 
WriteToMiscAndResultFileRebootToUpdater(const struct UpdateMessage & updateMsg)99 static 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");
118     while (true) {
119         pause();
120     }
121 #else
122     return true;
123 #endif
124 }
125 
IsPackagePath(const std::string & path)126 static 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 
AddPkgPath(struct UpdateMessage & msg,size_t updateOffset,const std::vector<std::string> & packageName)135 static 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 
RebootAndInstallSdcardPackage(const std::string & miscFile,const std::vector<std::string> & packageName)159 bool 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 
RebootAndInstallUpgradePackage(const std::string & miscFile,const std::vector<std::string> & packageName,const std::string & upgradeType)178 int 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 
208     int addRet = AddPkgPath(updateMsg, static_cast<size_t>(ret), packageName);
209     if (addRet != 0) {
210         return addRet;
211     }
212     if (upgradeType == UPGRADE_TYPE_OTA) {
213         WriteToMiscAndResultFileRebootToUpdater(updateMsg);
214     } else {
215         WriteToMiscAndRebootToUpdater(updateMsg);
216     }
217 
218     // Never get here.
219     return 0;
220 }
221 
RebootAndCleanUserData(const std::string & miscFile,const std::string & cmd)222 bool RebootAndCleanUserData(const std::string &miscFile, const std::string &cmd)
223 {
224     if (miscFile.empty() || cmd.empty()) {
225         LOG(ERROR) << "updaterkits: invalid argument. one of arugments is empty";
226         return false;
227     }
228 
229     // Write package name to misc, then trigger reboot.
230     struct UpdateMessage updateMsg {};
231     if (strncpy_s(updateMsg.update, sizeof(updateMsg.update), cmd.c_str(), cmd.size()) != EOK) {
232         LOG(ERROR) << "updaterkits: copy updater message failed";
233         return false;
234     }
235 
236     WriteToMiscAndRebootToUpdater(updateMsg);
237 
238     // Never get here.
239     return true;
240 }
241