1 /*
2 * Copyright (c) 2021-2023 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 <chrono>
16 #include <dirent.h>
17 #include <fcntl.h>
18 #include <sys/mount.h>
19 #include <sys/stat.h>
20 #include <sys/statvfs.h>
21
22 #include "applypatch/partition_record.h"
23 #include "flashd/flashd.h"
24 #include "log/log.h"
25 #include "misc_info/misc_info.h"
26 #include "package/pkg_manager.h"
27 #include "securec.h"
28 #include "updater/updater.h"
29 #include "updater/updater_const.h"
30 #include "updater_main.h"
31 #include "utils.h"
32
33 namespace Updater {
34 using namespace Hpackage;
35 using namespace Updater::Utils;
36
DeleteUpdaterPath(const std::string & path)37 bool DeleteUpdaterPath(const std::string &path)
38 {
39 auto pDir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(path.c_str()), closedir);
40 if (pDir == nullptr) {
41 LOG(INFO) << "Can not open dir";
42 return true;
43 }
44 bool sdcardTmp = false;
45 if (path.find("sdcard") != std::string::npos) {
46 sdcardTmp = true;
47 }
48 struct dirent *dp = nullptr;
49 while ((dp = readdir(pDir.get())) != nullptr) {
50 std::string currentName(dp->d_name);
51 if (currentName[0] == '.' || (currentName.compare("log") == 0) ||
52 (currentName.compare(UPDATER_RESULT_FILE) == 0) ||
53 (currentName.compare(UPDATER_LOCALE_FILE) == 0)) {
54 continue;
55 }
56 if (sdcardTmp && currentName.find(SDCARD_PACKAGE_SUFFIX) != std::string::npos) {
57 continue;
58 }
59 std::string tmpName(path);
60 tmpName.append("/" + currentName);
61 if (IsDirExist(tmpName)) {
62 DeleteUpdaterPath(tmpName);
63 }
64 #ifndef UPDATER_UT
65 remove(tmpName.c_str());
66 #endif
67 }
68 return true;
69 }
70
ClearMisc()71 bool ClearMisc()
72 {
73 struct UpdateMessage cleanBoot {};
74 if (!WriteUpdaterMiscMsg(cleanBoot)) {
75 LOG(ERROR) << "ClearMisc clear boot message to misc failed";
76 return false;
77 }
78 auto miscBlockDev = GetBlockDeviceByMountPoint(MISC_PATH);
79 if (miscBlockDev.empty()) {
80 LOG(INFO) << "cannot get block device of partition";
81 miscBlockDev = MISC_FILE;
82 }
83 LOG(INFO) << "ClearMisc::misc path : " << miscBlockDev;
84 auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(miscBlockDev.c_str(), "rb+"), fclose);
85 if (fp == nullptr) {
86 LOG(ERROR) << "WriteVersionCode fopen failed" << " : " << strerror(errno);
87 return false;
88 }
89 if (fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET) != 0) {
90 LOG(ERROR) << "ClearMisc fseek failed";
91 return false;
92 }
93 off_t clearOffset = 0;
94 if (fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) != 1) {
95 LOG(ERROR) << "ClearMisc write misc initOffset 0 failed" << " : " << strerror(errno);
96 return false;
97 }
98
99 struct PartitionRecordInfo cleanPartition {};
100 for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset +=
101 sizeof(PartitionRecordInfo)) {
102 if (fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET) != 0) {
103 LOG(ERROR) << "ClearMisc fseek failed";
104 return false;
105 }
106 if (fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) != 1) {
107 LOG(ERROR) << "ClearMisc write misc cleanPartition failed" << " : " << strerror(errno);
108 return false;
109 }
110 }
111 return true;
112 }
113
IsSDCardExist(const std::string & sdcardPath)114 bool IsSDCardExist(const std::string &sdcardPath)
115 {
116 // Record system error codes.
117 int save_errno = errno;
118 struct stat st {};
119 if (stat(sdcardPath.c_str(), &st) < 0) {
120 return false;
121 } else {
122 errno = save_errno;
123 return true;
124 }
125 }
126
PostUpdater(bool clearMisc)127 void PostUpdater(bool clearMisc)
128 {
129 STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater";
130
131 (void)SetupPartitions();
132 UpdaterInit::GetInstance().InvokeEvent(UPDATER_POST_INIT_EVENT);
133 // clear update misc partition.
134 if (clearMisc && !ClearMisc()) {
135 LOG(ERROR) << "PostUpdater clear misc failed";
136 }
137 if (!access(COMMAND_FILE, 0) && unlink(COMMAND_FILE) != 0) {
138 LOG(ERROR) << "Delete command failed";
139 }
140
141 // delete updater tmp files
142 if (access(UPDATER_PATH, 0) == 0 && access(SDCARD_CARD_PATH, 0) != 0 && !DeleteUpdaterPath(UPDATER_PATH)) {
143 LOG(ERROR) << "DeleteUpdaterPath failed";
144 }
145 if (access(SDCARD_CARD_PATH, 0) == 0 && !DeleteUpdaterPath(SDCARD_CARD_PATH)) {
146 LOG(ERROR) << "Delete sdcard path failed";
147 }
148 if (access(Flashd::FLASHD_FILE_PATH, 0) == 0 && !DeleteUpdaterPath(Flashd::FLASHD_FILE_PATH)) {
149 LOG(ERROR) << "DeleteUpdaterPath failed";
150 }
151
152 SaveLogs();
153 }
154
InitMode(void) const155 void BootMode::InitMode(void) const
156 {
157 InitUpdaterLogger(modeName, TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH);
158 #ifdef UPDATER_BUILD_VARIANT_USER
159 SetLogLevel(INFO);
160 #else
161 SetLogLevel(DEBUG);
162 #endif
163 LoadFstab();
164 STAGE(UPDATE_STAGE_OUT) << "Start " << modeName;
165 SetParameter(modePara.c_str(), "1");
166 }
167
IsUpdater(const UpdateMessage & boot)168 bool IsUpdater(const UpdateMessage &boot)
169 {
170 return !IsFlashd(boot) && strncmp(boot.command, "boot_updater", sizeof("boot_updater") - 1) == 0;
171 }
172
IsFlashd(const UpdateMessage & boot)173 bool IsFlashd(const UpdateMessage &boot)
174 {
175 return strncmp(boot.update, "boot_flash", sizeof("boot_flash") - 1) == 0;
176 }
177
GetBootModes(void)178 std::vector<BootMode> &GetBootModes(void)
179 {
180 static std::vector<BootMode> bootModes {};
181 return bootModes;
182 }
183
RegisterMode(const BootMode & mode)184 void RegisterMode(const BootMode &mode)
185 {
186 GetBootModes().push_back(mode);
187 }
188
SelectMode(const UpdateMessage & boot)189 std::optional<BootMode> SelectMode(const UpdateMessage &boot)
190 {
191 const auto &modes = GetBootModes();
192
193 // select modes by bootMode.cond which would check misc message
194 auto it = std::find_if(modes.begin(), modes.end(), [&boot] (const auto &bootMode) {
195 if (bootMode.cond != nullptr && bootMode.cond(boot)) {
196 return true;
197 }
198 LOG(WARNING) << "condition for mode " << bootMode.modeName << " is not satisfied";
199 return false;
200 });
201 // misc check failed for each mode, then enter updater mode
202 if (it == modes.end() || it->entryFunc == nullptr) {
203 LOG(WARNING) << "find valid mode failed, enter updater Mode";
204 return std::nullopt;
205 }
206
207 LOG(INFO) << "enter " << it->modeName << " mode";
208 return *it;
209 }
210
SetMessageToMisc(const std::string & miscCmd,const int message,const std::string headInfo)211 void SetMessageToMisc(const std::string &miscCmd, const int message, const std::string headInfo)
212 {
213 if (headInfo.empty()) {
214 return;
215 }
216 std::vector<std::string> args = ParseParams(0, nullptr);
217 struct UpdateMessage msg {};
218 if (strncpy_s(msg.command, sizeof(msg.command), miscCmd.c_str(), miscCmd.size() + 1) != EOK) {
219 LOG(ERROR) << "SetMessageToMisc strncpy_s failed";
220 return;
221 }
222 for (const auto& arg : args) {
223 if (arg.find(headInfo) == std::string::npos) {
224 if (strncat_s(msg.update, sizeof(msg.update), arg.c_str(), strlen(arg.c_str()) + 1) != EOK) {
225 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
226 return;
227 }
228 if (strncat_s(msg.update, sizeof(msg.update), "\n", strlen("\n") + 1) != EOK) {
229 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
230 return;
231 }
232 }
233 }
234 char buffer[128] {}; // 128 : set headInfo size
235 if (headInfo == "sdcard_update") {
236 if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s", headInfo.c_str()) == -1) {
237 LOG(ERROR) << "SetMessageToMisc strncpy_s failed";
238 return;
239 }
240 } else {
241 if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s=%d", headInfo.c_str(), message) == -1) {
242 LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
243 return;
244 }
245 }
246 if (strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1) != EOK) {
247 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
248 return;
249 }
250 if (WriteUpdaterMiscMsg(msg) != true) {
251 LOG(ERROR) << "Write command to misc failed.";
252 }
253 }
254 } // namespace Updater
255