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 "pkg_utils.h"
16 #ifdef _WIN32
17 #include <windows.h>
18 #else
19 #include <climits>
20 #include <sys/mman.h>
21 #endif
22 #include <cstring>
23 #include <fcntl.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include "utils.h"
27
28 namespace Hpackage {
29 #ifdef _WIN32
30 #undef ERROR
31 #endif
32
33 #ifdef __APPLE__
34 #define MAP_POPULATE 0x08000
35 #endif
36
37 constexpr int32_t MIN_YEAR = 80;
38 constexpr uint32_t TM_YEAR_BITS = 9;
39 constexpr uint32_t TM_MON_BITS = 5;
40 constexpr uint32_t TM_MIN_BITS = 5;
41 constexpr uint32_t TM_HOUR_BITS = 11;
42 constexpr uint32_t BYTE_SIZE = 8;
43 constexpr uint32_t SECOND_BUFFER = 2;
44 constexpr uint32_t THIRD_BUFFER = 3;
45 constexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4;
46
47 using namespace Updater::Utils;
48
GetFilePath(const std::string & fileName)49 std::string GetFilePath(const std::string &fileName)
50 {
51 std::size_t pos = fileName.find_last_of('/');
52 if (pos == std::string::npos) {
53 pos = fileName.find_last_of('\\');
54 }
55 return fileName.substr(0, pos + 1);
56 }
57
GetFileSize(const std::string & fileName)58 size_t GetFileSize(const std::string &fileName)
59 {
60 char realPath[PATH_MAX] = { 0 };
61 #ifdef _WIN32
62 if (_fullpath(realPath, fileName.c_str(), PATH_MAX) == nullptr) {
63 #else
64 if (realpath(fileName.c_str(), realPath) == nullptr) {
65 #endif
66 PKG_LOGE("realPath is null");
67 return 0;
68 }
69 FILE *fp = fopen(realPath, "r");
70 if (fp == nullptr) {
71 PKG_LOGE("Invalid file %s", fileName.c_str());
72 return 0;
73 }
74
75 if (fseek(fp, 0, SEEK_END) < 0) {
76 PKG_LOGE("return value of fseek < 0");
77 fclose(fp);
78 return 0;
79 }
80 long size = ftell(fp);
81 if (size < 0) {
82 PKG_LOGE("return value of ftell < 0");
83 fclose(fp);
84 return 0;
85 }
86 fclose(fp);
87 // return file size in bytes
88 return static_cast<size_t>(size);
89 }
90
91 std::string GetName(const std::string &filePath)
92 {
93 return filePath.substr(filePath.find_last_of("/") + 1);
94 }
95
96 int32_t CheckFile(const std::string &fileName, int type)
97 {
98 // Check if the directory of @fileName is exist or has write permission
99 // If not, Create the directory first.
100 std::string path = GetFilePath(fileName);
101 if (path.empty()) {
102 return PKG_SUCCESS;
103 }
104 if (access(path.c_str(), F_OK) == -1) {
105 #ifdef __WIN32
106 mkdir(path.c_str());
107 #else
108 mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
109 #endif
110 }
111 int ret = -1;
112 if (type == PkgStream::PkgStreamType_Read) {
113 ret = access(path.c_str(), R_OK );
114 } else {
115 ret = access(path.c_str(), R_OK | W_OK);
116 }
117 if (ret == -1) {
118 PKG_LOGE("file %s no permission ", fileName.c_str());
119 return PKG_NONE_PERMISSION;
120 }
121 return PKG_SUCCESS;
122 }
123
124 uint8_t *AnonymousMap(const std::string &fileName, size_t size)
125 {
126 void *mappedData = nullptr;
127 // Map memory for file
128 mappedData = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_POPULATE | MAP_ANON, -1, 0);
129 if (mappedData == MAP_FAILED) {
130 PKG_LOGE("Failed to alloc memory for file %s ", fileName.c_str());
131 return nullptr;
132 }
133 return static_cast<uint8_t *>(mappedData);
134 }
135
136 uint8_t *FileMap(const std::string &path)
137 {
138 if (access(path.c_str(), 0) != 0) {
139 PKG_LOGE("Path not exist %s", path.c_str());
140 return nullptr;
141 }
142 int fd = open(path.c_str(), O_RDONLY);
143 if (fd < 0) {
144 PKG_LOGE("Failed to open file");
145 return nullptr;
146 }
147 size_t size = GetFileSize(path);
148 void *mappedData = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
149 if (mappedData == MAP_FAILED) {
150 close(fd);
151 PKG_LOGE("Failed to mmap file");
152 return nullptr;
153 }
154 close(fd);
155 return static_cast<uint8_t *>(mappedData);
156 }
157
158 void ReleaseMemory(uint8_t *memMap, size_t size)
159 {
160 if (size <= 0 || memMap == nullptr) {
161 PKG_LOGE("Size must > 0");
162 return;
163 }
164 // Flush memory and release memory.
165 msync(static_cast<void *>(memMap), size, MS_ASYNC);
166 munmap(memMap, size);
167 }
168
169 std::string GetCurrPath()
170 {
171 std::string path;
172 char *buffer = getcwd(nullptr, 0);
173 if (buffer == nullptr) {
174 PKG_LOGE("getcwd error");
175 return "./";
176 }
177 path.assign(buffer);
178 free(buffer);
179 return path + "/";
180 }
181
182 void ExtraTimeAndDate(time_t when, uint16_t &date, uint16_t &time)
183 {
184 when = static_cast<time_t>((static_cast<unsigned long>(when) + 1) & (~1));
185 struct tm nowTime {};
186 #ifdef __WIN32
187 localtime_s(&nowTime, &when);
188 #else
189 localtime_r(&when, &nowTime);
190 #endif
191 int year = nowTime.tm_year;
192 if (year < MIN_YEAR) {
193 year = MIN_YEAR;
194 }
195 date = static_cast<uint16_t>(static_cast<uint16_t>(year - MIN_YEAR) << TM_YEAR_BITS);
196 date |= static_cast<uint16_t>(static_cast<uint16_t>(nowTime.tm_mon + 1) << TM_MON_BITS);
197 date |= static_cast<uint16_t>(nowTime.tm_mday);
198 time = static_cast<uint16_t>(static_cast<uint16_t>(nowTime.tm_hour) << TM_HOUR_BITS);
199 time |= static_cast<uint16_t>(static_cast<uint16_t>(nowTime.tm_min) << TM_MIN_BITS);
200 time |= static_cast<uint16_t>(static_cast<uint16_t>(nowTime.tm_sec) >> 1);
201 }
202
203 uint32_t ReadLE32(const uint8_t *buff)
204 {
205 if (buff == nullptr) {
206 PKG_LOGE("buff is null");
207 return 0;
208 }
209 size_t offset = 0;
210 uint32_t value32 = buff[0];
211 offset += BYTE_SIZE;
212 value32 += static_cast<uint32_t>(static_cast<uint32_t>(buff[1]) << offset);
213 offset += BYTE_SIZE;
214 value32 += static_cast<uint32_t>(static_cast<uint32_t>(buff[SECOND_BUFFER]) << offset);
215 offset += BYTE_SIZE;
216 value32 += static_cast<uint32_t>(static_cast<uint32_t>(buff[THIRD_BUFFER]) << offset);
217 return value32;
218 }
219
220 uint64_t ReadLE64(const uint8_t *buff)
221 {
222 if (buff == nullptr) {
223 PKG_LOGE("buff is null");
224 return 0;
225 }
226 uint32_t low = ReadLE32(buff);
227 uint32_t high = ReadLE32(buff + sizeof(uint32_t));
228 uint64_t value = ((static_cast<uint64_t>(high)) << (BYTE_SIZE * sizeof(uint32_t))) | low;
229 return value;
230 }
231
232 void WriteLE32(uint8_t *buff, uint32_t value)
233 {
234 if (buff == nullptr) {
235 PKG_LOGE("buff is null");
236 return;
237 }
238 size_t offset = 0;
239 buff[0] = static_cast<uint8_t>(value);
240 offset += BYTE_SIZE;
241 buff[1] = static_cast<uint8_t>(value >> offset);
242 offset += BYTE_SIZE;
243 buff[SECOND_BUFFER] = static_cast<uint8_t>(value >> offset);
244 offset += BYTE_SIZE;
245 buff[THIRD_BUFFER] = static_cast<uint8_t>(value >> offset);
246 }
247
248 uint16_t ReadLE16(const uint8_t *buff)
249 {
250 if (buff == nullptr) {
251 PKG_LOGE("buff is null");
252 return 0;
253 }
254 uint16_t value16 = buff[0];
255 value16 += static_cast<uint16_t>(buff[1] << BYTE_SIZE);
256 return value16;
257 }
258
259 void WriteLE16(uint8_t *buff, uint16_t value)
260 {
261 if (buff == nullptr) {
262 PKG_LOGE("buff is null");
263 return;
264 }
265 buff[0] = static_cast<uint8_t>(value);
266 buff[1] = static_cast<uint8_t>(value >> BYTE_SIZE);
267 }
268
269 std::string ConvertShaHex(const std::vector<uint8_t> &shaDigest)
270 {
271 const std::string hexChars = "0123456789abcdef";
272 std::string haxSha256 = "";
273 unsigned int c;
274 for (size_t i = 0; i < shaDigest.size(); ++i) {
275 auto d = shaDigest[i];
276 c = (d >> SHIFT_RIGHT_FOUR_BITS) & 0xf; // last 4 bits
277 haxSha256.push_back(hexChars[c]);
278 haxSha256.push_back(hexChars[d & 0xf]);
279 }
280 return haxSha256;
281 }
282 } // namespace Hpackage
283
284 #ifdef _WIN32
mmap(void * addr,size_t length,int prot,int flags,int fd,size_t offset)285 void *mmap([[maybe_unused]] void *addr, [[maybe_unused]] size_t length,
286 [[maybe_unused]] int prot, [[maybe_unused]] int flags, int fd, [[maybe_unused]] size_t offset)
287 {
288 HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
289 if (FileHandle == INVALID_HANDLE_VALUE) {
290 return MAP_FAILED;
291 }
292 HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, PAGE_READONLY, 0, 0, 0);
293 if (FileMappingHandle == nullptr) {
294 PKG_LOGE("CreateFileMappingW Failed");
295 return MAP_FAILED;
296 }
297 void *mapAddr = ::MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0);
298 if (mapAddr == nullptr) {
299 PKG_LOGE("MapViewOfFile Failed");
300 ::CloseHandle(FileMappingHandle);
301 return MAP_FAILED;
302 }
303 ::CloseHandle(FileMappingHandle);
304 return mapAddr;
305 }
306
msync(void * addr,size_t len,int flags)307 int msync(void *addr, size_t len, [[maybe_unused]] int flags)
308 {
309 return FlushViewOfFile(addr, len);
310 }
311
munmap(void * addr,size_t len)312 int munmap(void *addr, [[maybe_unused]] size_t len)
313 {
314 return !UnmapViewOfFile(addr);
315 }
316 #endif
317