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
16 #include "utils.h"
17 #include <algorithm>
18 #include <cerrno>
19 #include <cstdint>
20 #include <cstdlib>
21 #include <dirent.h>
22 #include <limits>
23 #include <linux/reboot.h>
24 #include <string>
25 #include <sys/stat.h>
26 #include <sys/syscall.h>
27 #include <unistd.h>
28 #include <vector>
29 #include "fs_manager/mount.h"
30 #include "log/log.h"
31 #include "misc_info/misc_info.h"
32 #include "package/pkg_manager.h"
33 #include "securec.h"
34 #include "updater/updater_const.h"
35
36 namespace updater {
37 using namespace hpackage;
38
39 namespace utils {
40 constexpr uint32_t MAX_PATH_LEN = 256;
41 constexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4;
DeleteFile(const std::string & filename)42 int32_t DeleteFile(const std::string& filename)
43 {
44 UPDATER_ERROR_CHECK (!filename.empty(), "Invalid filename", return -1);
45 if (unlink(filename.c_str()) == -1 && errno != ENOENT) {
46 LOG(ERROR) << "unlink " << filename << " failed";
47 return -1;
48 }
49 return 0;
50 }
51
MkdirRecursive(const std::string & pathName,mode_t mode)52 int MkdirRecursive(const std::string &pathName, mode_t mode)
53 {
54 size_t slashPos = 0;
55 struct stat info {};
56 while (true) {
57 slashPos = pathName.find_first_of("/", slashPos);
58 UPDATER_CHECK_ONLY_RETURN(slashPos != std::string::npos, break);
59 if (slashPos == 0) {
60 slashPos++;
61 continue;
62 }
63 UPDATER_ERROR_CHECK(slashPos <= MAX_PATH_LEN, "path too long for mkdir", return -1);
64 auto subDir = pathName.substr(0, slashPos);
65 std::cout << "subDir : " << subDir << std::endl;
66 if (stat(subDir.c_str(), &info) != 0) {
67 int ret = mkdir(subDir.c_str(), mode);
68 UPDATER_CHECK_ONLY_RETURN(!(ret && errno != EEXIST), return ret);
69 }
70 slashPos++;
71 }
72 int ret = mkdir(pathName.c_str(), mode);
73 UPDATER_CHECK_ONLY_RETURN(!(ret && errno != EEXIST), return ret);
74 return 0;
75 }
76
GetFilesFromDirectory(const std::string & path,std::vector<std::string> & files,bool isRecursive)77 int64_t GetFilesFromDirectory(const std::string &path, std::vector<std::string> &files,
78 bool isRecursive)
79 {
80 struct stat sb {};
81 UPDATER_ERROR_CHECK (stat(path.c_str(), &sb) != -1, "Failed to stat", return -1);
82 DIR *dirp = opendir(path.c_str());
83 struct dirent *dp;
84 int64_t totalSize = 0;
85 while ((dp = readdir(dirp)) != nullptr) {
86 std::string fileName = path + "/" + dp->d_name;
87 struct stat st {};
88 if (stat(fileName.c_str(), &st) == 0) {
89 std::string tmpName = dp->d_name;
90 if (tmpName == "." || tmpName == "..") {
91 continue;
92 }
93 if (isRecursive && S_ISDIR(st.st_mode)) {
94 totalSize += GetFilesFromDirectory(fileName, files, isRecursive);
95 }
96 files.push_back(fileName);
97 totalSize += st.st_size;
98 }
99 }
100 closedir(dirp);
101 return totalSize;
102 }
103
SplitString(const std::string & str,const std::string del)104 std::vector<std::string> SplitString(const std::string &str, const std::string del)
105 {
106 std::vector<std::string> result;
107 size_t found = std::string::npos;
108 size_t start = 0;
109 while (true) {
110 found = str.find_first_of(del, start);
111 result.push_back(str.substr(start, found - start));
112 if (found == std::string::npos) {
113 break;
114 }
115 start = found + 1;
116 }
117 return result;
118 }
119
Trim(const std::string & str)120 std::string Trim(const std::string &str)
121 {
122 if (str.empty()) {
123 LOG(ERROR) << "str is empty";
124 return str;
125 }
126 size_t start = 0;
127 size_t end = str.size() - 1;
128 while (start < str.size()) {
129 if (!isspace(str[start])) {
130 break;
131 }
132 start++;
133 }
134 while (start < end) {
135 if (!isspace(str[end])) {
136 break;
137 }
138 end--;
139 }
140 if (end < start) {
141 return "";
142 }
143 return str.substr(start, end - start + 1);
144 }
145
ConvertSha256Hex(const uint8_t * shaDigest,size_t length)146 std::string ConvertSha256Hex(const uint8_t* shaDigest, size_t length)
147 {
148 const std::string hexChars = "0123456789abcdef";
149 std::string haxSha256 = "";
150 unsigned int c;
151 for (size_t i = 0; i < length; ++i) {
152 auto d = shaDigest[i];
153 c = (d >> SHIFT_RIGHT_FOUR_BITS) & 0xf; // last 4 bits
154 haxSha256.push_back(hexChars[c]);
155 haxSha256.push_back(hexChars[d & 0xf]);
156 }
157 return haxSha256;
158 }
159
DoReboot(const std::string & rebootTarget,const std::string & extData)160 void DoReboot(const std::string& rebootTarget, const std::string &extData)
161 {
162 LOG(INFO) << ", rebootTarget: " << rebootTarget;
163 static const int32_t maxCommandSize = 16;
164 LoadFstab();
165 auto miscBlockDevice = GetBlockDeviceByMountPoint("/misc");
166 struct UpdateMessage msg;
167 if (rebootTarget.empty()) {
168 UPDATER_ERROR_CHECK(!memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE), "Memset_s failed", return);
169 if (WriteUpdaterMessage(miscBlockDevice, msg) != true) {
170 LOG(INFO) << "DoReboot: WriteUpdaterMessage empty error";
171 return;
172 }
173 sync();
174 } else {
175 int result = 0;
176 bool ret = ReadUpdaterMessage(miscBlockDevice, msg);
177 UPDATER_ERROR_CHECK(ret == true, "DoReboot read misc failed", return);
178 if (rebootTarget == "updater" && strcmp(msg.command, "boot_updater") != 0) {
179 result = strcpy_s(msg.command, maxCommandSize, "boot_updater");
180 msg.command[maxCommandSize] = 0;
181 } else if (rebootTarget == "flashd" && strcmp(msg.command, "flashd") != 0) {
182 result = strcpy_s(msg.command, maxCommandSize, "boot_flash");
183 msg.command[maxCommandSize] = 0;
184 } else if (rebootTarget == "bootloader" && strcmp(msg.command, "boot_loader") != 0) {
185 result = strcpy_s(msg.command, maxCommandSize, "boot_loader");
186 msg.command[maxCommandSize] = 0;
187 }
188 UPDATER_ERROR_CHECK(result == 0, "strcpy failed", return);
189 if (!extData.empty()) {
190 result = strcpy_s(msg.update, MAX_UPDATE_SIZE - 1, extData.c_str());
191 UPDATER_ERROR_CHECK(result == 0, "Failed to copy update", return);
192 msg.update[MAX_UPDATE_SIZE - 1] = 0;
193 } else {
194 UPDATER_ERROR_CHECK(!memset_s(msg.update, MAX_UPDATE_SIZE, 0, MAX_UPDATE_SIZE), "Memset_s failed", return);
195 }
196 if (WriteUpdaterMessage(miscBlockDevice, msg) != true) {
197 LOG(INFO) << "DoReboot: WriteUpdaterMessage boot_updater error";
198 return;
199 }
200 sync();
201 }
202 #ifndef UPDATER_UT
203 syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str());
204 while (true) {
205 pause();
206 }
207 #else
208 return;
209 #endif
210 }
211
GetCertName()212 std::string GetCertName()
213 {
214 #ifndef UPDATER_UT
215 static std::string signingCertName = "/certificate/signing_cert.crt";
216 #else
217 static std::string signingCertName = "/data/updater/src/signing_cert.crt";
218 #endif
219 return signingCertName;
220 }
221
WriteFully(int fd,const void * data,size_t size)222 bool WriteFully(int fd, const void *data, size_t size)
223 {
224 ssize_t written = 0;
225 size_t rest = size;
226
227 auto p = reinterpret_cast<const uint8_t*>(data);
228 while (rest > 0) {
229 do {
230 written = write(fd, p, rest);
231 } while (written < 0 && errno == EINTR);
232
233 if (written < 0) {
234 return false;
235 }
236 p += written;
237 rest -= written;
238 }
239 return true;
240 }
241
ReadFully(int fd,void * data,size_t size)242 bool ReadFully(int fd, void *data, size_t size)
243 {
244 auto p = reinterpret_cast<uint8_t *>(data);
245 size_t remaining = size;
246 while (remaining > 0) {
247 ssize_t sread = read(fd, p, remaining);
248 UPDATER_ERROR_CHECK (sread > 0, "Utils::ReadFully run error", return false);
249 p += sread;
250 remaining -= sread;
251 }
252 return true;
253 }
254
ReadFileToString(int fd,std::string & content)255 bool ReadFileToString(int fd, std::string &content)
256 {
257 struct stat sb {};
258 if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
259 content.resize(sb.st_size);
260 }
261 ssize_t n;
262 size_t remaining = sb.st_size;
263 auto p = reinterpret_cast<char *>(content.data());
264 while (remaining > 0) {
265 n = read(fd, p, remaining);
266 UPDATER_CHECK_ONLY_RETURN (n > 0, return false);
267 p += n;
268 remaining -= n;
269 }
270 return true;
271 }
272
WriteStringToFile(int fd,const std::string & content)273 bool WriteStringToFile(int fd, const std::string& content)
274 {
275 const char *p = content.data();
276 size_t remaining = content.size();
277 while (remaining > 0) {
278 ssize_t n = write(fd, p, remaining);
279 UPDATER_CHECK_ONLY_RETURN (n != -1, return false);
280 p += n;
281 remaining -= n;
282 }
283 return true;
284 }
285
GetLocalBoardId()286 std::string GetLocalBoardId()
287 {
288 return "HI3516";
289 }
290 } // utils
291 } // namespace updater
292