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 28namespace Hpackage { 29#ifdef _WIN32 30#undef ERROR 31#endif 32 33#ifdef __APPLE__ 34#define MAP_POPULATE 0x08000 35#endif 36 37constexpr int32_t MIN_YEAR = 80; 38constexpr uint32_t TM_YEAR_BITS = 9; 39constexpr uint32_t TM_MON_BITS = 5; 40constexpr uint32_t TM_MIN_BITS = 5; 41constexpr uint32_t TM_HOUR_BITS = 11; 42constexpr uint32_t BYTE_SIZE = 8; 43constexpr uint32_t SECOND_BUFFER = 2; 44constexpr uint32_t THIRD_BUFFER = 3; 45constexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4; 46 47using namespace Updater::Utils; 48 49std::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 58size_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 91std::string GetName(const std::string &filePath) 92{ 93 return filePath.substr(filePath.find_last_of("/") + 1); 94} 95 96int32_t CreatDirectory(const std::string &path, mode_t mode) 97{ 98 size_t slashPos = 0; 99 struct stat info {}; 100 while (true) { 101 slashPos = path.find_first_of("/", slashPos); 102 if (slashPos == std::string::npos) { 103 break; 104 } 105 if (slashPos == 0) { 106 slashPos++; 107 continue; 108 } 109 if (slashPos > PATH_MAX) { 110 PKG_LOGE("path too long"); 111 return -1; 112 } 113 auto subDir = path.substr(0, slashPos); 114 if (stat(subDir.c_str(), &info) != 0) { 115#ifdef __WIN32 116 int ret = mkdir(subDir.c_str()); 117#else 118 int ret = mkdir(subDir.c_str(), mode); 119#endif 120 if (ret && errno != EEXIST) { 121 return ret; 122 } 123 } 124 slashPos++; 125 } 126#ifdef __WIN32 127 int ret = mkdir(path.c_str()); 128#else 129 int ret = mkdir(path.c_str(), mode); 130#endif 131 if (ret && errno != EEXIST) { 132 return ret; 133 } 134 return 0; 135} 136 137int32_t CheckFile(const std::string &fileName, int type) 138{ 139 // Check if the directory of @fileName is exist or has write permission 140 // If not, Create the directory first. 141 std::string path = GetFilePath(fileName); 142 if (path.empty()) { 143 return PKG_SUCCESS; 144 } 145 if (access(path.c_str(), F_OK) == -1) { 146 CreatDirectory(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); 147 } 148 int ret = -1; 149 if (type == PkgStream::PkgStreamType_Read) { 150 ret = access(path.c_str(), R_OK); 151 } else { 152 ret = access(path.c_str(), R_OK | W_OK); 153 } 154 if (ret == -1) { 155 PKG_LOGE("file %s no permission ", fileName.c_str()); 156 return PKG_NONE_PERMISSION; 157 } 158 return PKG_SUCCESS; 159} 160 161uint8_t *AnonymousMap(const std::string &fileName, size_t size) 162{ 163 void *mappedData = nullptr; 164 // Map memory for file 165 mappedData = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_POPULATE | MAP_ANON, -1, 0); 166 if (mappedData == MAP_FAILED) { 167 PKG_LOGE("Failed to alloc memory for file %s ", fileName.c_str()); 168 return nullptr; 169 } 170 return static_cast<uint8_t *>(mappedData); 171} 172 173uint8_t *FileMap(const std::string &path) 174{ 175 if (access(path.c_str(), 0) != 0) { 176 PKG_LOGE("Path not exist %s", path.c_str()); 177 return nullptr; 178 } 179 int fd = open(path.c_str(), O_RDONLY); 180 if (fd < 0) { 181 PKG_LOGE("Failed to open file"); 182 return nullptr; 183 } 184 size_t size = GetFileSize(path); 185 void *mappedData = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0); 186 if (mappedData == MAP_FAILED) { 187 close(fd); 188 PKG_LOGE("Failed to mmap file"); 189 return nullptr; 190 } 191 close(fd); 192 return static_cast<uint8_t *>(mappedData); 193} 194 195void ReleaseMemory(uint8_t *memMap, size_t size) 196{ 197 if (size <= 0 || memMap == nullptr) { 198 PKG_LOGE("Size must > 0"); 199 return; 200 } 201 // Flush memory and release memory. 202 msync(static_cast<void *>(memMap), size, MS_ASYNC); 203 munmap(memMap, size); 204} 205 206std::string GetCurrPath() 207{ 208 std::string path; 209 char *buffer = getcwd(nullptr, 0); 210 if (buffer == nullptr) { 211 PKG_LOGE("getcwd error"); 212 return "./"; 213 } 214 path.assign(buffer); 215 free(buffer); 216 return path + "/"; 217} 218 219void ExtraTimeAndDate(time_t when, uint16_t &date, uint16_t &time) 220{ 221 when = static_cast<time_t>((static_cast<unsigned long>(when) + 1) & (~1)); 222 struct tm nowTime {}; 223#ifdef __WIN32 224 localtime_s(&nowTime, &when); 225#else 226 localtime_r(&when, &nowTime); 227#endif 228 int year = nowTime.tm_year; 229 if (year < MIN_YEAR) { 230 year = MIN_YEAR; 231 } 232 date = static_cast<uint16_t>(static_cast<uint16_t>(year - MIN_YEAR) << TM_YEAR_BITS); 233 date |= static_cast<uint16_t>(static_cast<uint16_t>(nowTime.tm_mon + 1) << TM_MON_BITS); 234 date |= static_cast<uint16_t>(nowTime.tm_mday); 235 time = static_cast<uint16_t>(static_cast<uint16_t>(nowTime.tm_hour) << TM_HOUR_BITS); 236 time |= static_cast<uint16_t>(static_cast<uint16_t>(nowTime.tm_min) << TM_MIN_BITS); 237 time |= static_cast<uint16_t>(static_cast<uint16_t>(nowTime.tm_sec) >> 1); 238} 239 240uint32_t ReadLE32(const uint8_t *buff) 241{ 242 if (buff == nullptr) { 243 PKG_LOGE("buff is null"); 244 return 0; 245 } 246 size_t offset = 0; 247 uint32_t value32 = buff[0]; 248 offset += BYTE_SIZE; 249 value32 += static_cast<uint32_t>(static_cast<uint32_t>(buff[1]) << offset); 250 offset += BYTE_SIZE; 251 value32 += static_cast<uint32_t>(static_cast<uint32_t>(buff[SECOND_BUFFER]) << offset); 252 offset += BYTE_SIZE; 253 value32 += static_cast<uint32_t>(static_cast<uint32_t>(buff[THIRD_BUFFER]) << offset); 254 return value32; 255} 256 257uint64_t ReadLE64(const uint8_t *buff) 258{ 259 if (buff == nullptr) { 260 PKG_LOGE("buff is null"); 261 return 0; 262 } 263 uint32_t low = ReadLE32(buff); 264 uint32_t high = ReadLE32(buff + sizeof(uint32_t)); 265 uint64_t value = ((static_cast<uint64_t>(high)) << (BYTE_SIZE * sizeof(uint32_t))) | low; 266 return value; 267} 268 269void WriteLE32(uint8_t *buff, uint32_t value) 270{ 271 if (buff == nullptr) { 272 PKG_LOGE("buff is null"); 273 return; 274 } 275 size_t offset = 0; 276 buff[0] = static_cast<uint8_t>(value); 277 offset += BYTE_SIZE; 278 buff[1] = static_cast<uint8_t>(value >> offset); 279 offset += BYTE_SIZE; 280 buff[SECOND_BUFFER] = static_cast<uint8_t>(value >> offset); 281 offset += BYTE_SIZE; 282 buff[THIRD_BUFFER] = static_cast<uint8_t>(value >> offset); 283} 284 285uint16_t ReadLE16(const uint8_t *buff) 286{ 287 if (buff == nullptr) { 288 PKG_LOGE("buff is null"); 289 return 0; 290 } 291 uint16_t value16 = buff[0]; 292 value16 += static_cast<uint16_t>(buff[1] << BYTE_SIZE); 293 return value16; 294} 295 296void WriteLE16(uint8_t *buff, uint16_t value) 297{ 298 if (buff == nullptr) { 299 PKG_LOGE("buff is null"); 300 return; 301 } 302 buff[0] = static_cast<uint8_t>(value); 303 buff[1] = static_cast<uint8_t>(value >> BYTE_SIZE); 304} 305 306std::string ConvertShaHex(const std::vector<uint8_t> &shaDigest) 307{ 308 const std::string hexChars = "0123456789abcdef"; 309 std::string haxSha256 = ""; 310 unsigned int c; 311 for (size_t i = 0; i < shaDigest.size(); ++i) { 312 auto d = shaDigest[i]; 313 c = (d >> SHIFT_RIGHT_FOUR_BITS) & 0xf; // last 4 bits 314 haxSha256.push_back(hexChars[c]); 315 haxSha256.push_back(hexChars[d & 0xf]); 316 } 317 return haxSha256; 318} 319} // namespace Hpackage 320 321#ifdef _WIN32 322void *mmap([[maybe_unused]] void *addr, [[maybe_unused]] size_t length, 323 [[maybe_unused]] int prot, [[maybe_unused]] int flags, int fd, [[maybe_unused]] size_t offset) 324{ 325 HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); 326 if (FileHandle == INVALID_HANDLE_VALUE) { 327 return MAP_FAILED; 328 } 329 HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, PAGE_READONLY, 0, 0, 0); 330 if (FileMappingHandle == nullptr) { 331 PKG_LOGE("CreateFileMappingW Failed"); 332 return MAP_FAILED; 333 } 334 void *mapAddr = ::MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0); 335 if (mapAddr == nullptr) { 336 PKG_LOGE("MapViewOfFile Failed"); 337 ::CloseHandle(FileMappingHandle); 338 return MAP_FAILED; 339 } 340 ::CloseHandle(FileMappingHandle); 341 return mapAddr; 342} 343 344int msync(void *addr, size_t len, [[maybe_unused]] int flags) 345{ 346 return FlushViewOfFile(addr, len); 347} 348 349int munmap(void *addr, [[maybe_unused]] size_t len) 350{ 351 return !UnmapViewOfFile(addr); 352} 353#endif 354