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