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