1 /* 2 * Copyright (c) 2021-2024 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 "bundle_util.h" 17 18 #include <cinttypes> 19 #include <dirent.h> 20 #include <fcntl.h> 21 #include <fstream> 22 #include <sstream> 23 #include <sys/sendfile.h> 24 #include <sys/statfs.h> 25 26 #include "bundle_service_constants.h" 27 #ifdef CONFIG_POLOCY_ENABLE 28 #include "config_policy_utils.h" 29 #endif 30 #include "directory_ex.h" 31 #include "hitrace_meter.h" 32 #include "installd_client.h" 33 #include "ipc_skeleton.h" 34 #include "parameter.h" 35 #include "string_ex.h" 36 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED 37 #include "type_descriptor.h" 38 #include "utd_client.h" 39 #endif 40 41 namespace OHOS { 42 namespace AppExecFwk { 43 namespace { 44 const std::string::size_type EXPECT_SPLIT_SIZE = 2; 45 const size_t ORIGIN_STRING_LENGTH = 32; 46 constexpr char UUID_SEPARATOR = '-'; 47 const std::vector<int32_t> SEPARATOR_POSITIONS { 8, 13, 18, 23}; 48 const int64_t HALF_GB = 1024 * 1024 * 512; // 0.5GB 49 const int64_t SPACE_NEED_DOUBLE = 2; 50 const uint32_t UUID_LENGTH_MAX = 512; 51 static std::string g_deviceUdid; 52 static std::mutex g_mutex; 53 // hmdfs and sharefs config 54 constexpr const char* BUNDLE_ID_FILE = "appid"; 55 // single max hap size 56 constexpr int64_t ONE_GB = 1024 * 1024 * 1024; 57 constexpr int64_t MAX_HAP_SIZE = ONE_GB * 4; // 4GB 58 constexpr const char* ABC_FILE_PATH = "abc_files"; 59 constexpr const char* PGO_FILE_PATH = "pgo_files"; 60 const std::string EMPTY_STRING = ""; 61 constexpr int64_t DISK_REMAINING_SIZE_LIMIT = 1024 * 1024 * 10; // 10M 62 #ifdef CONFIG_POLOCY_ENABLE 63 const char* NO_DISABLING_CONFIG_PATH = "/etc/ability_runtime/resident_process_in_extreme_memory.json"; 64 #endif 65 const char* NO_DISABLING_CONFIG_PATH_DEFAULT = 66 "/system/etc/ability_runtime/resident_process_in_extreme_memory.json"; 67 } 68 69 std::mutex BundleUtil::g_mutex; 70 CheckFilePath(const std::string & bundlePath,std::string & realPath)71 ErrCode BundleUtil::CheckFilePath(const std::string &bundlePath, std::string &realPath) 72 { 73 if (!CheckFileName(bundlePath)) { 74 APP_LOGE("bundle file path invalid"); 75 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID; 76 } 77 if (!CheckFileType(bundlePath, ServiceConstants::INSTALL_FILE_SUFFIX) && 78 !CheckFileType(bundlePath, ServiceConstants::HSP_FILE_SUFFIX) && 79 !CheckFileType(bundlePath, ServiceConstants::QUICK_FIX_FILE_SUFFIX) && 80 !CheckFileType(bundlePath, ServiceConstants::CODE_SIGNATURE_FILE_SUFFIX)) { 81 APP_LOGE("file is not hap, hsp, hqf or sig"); 82 return ERR_APPEXECFWK_INSTALL_INVALID_HAP_NAME; 83 } 84 if (!PathToRealPath(bundlePath, realPath)) { 85 APP_LOGE("file is not real path"); 86 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID; 87 } 88 if (access(realPath.c_str(), F_OK) != 0) { 89 APP_LOGE("not access the bundle file path: %{public}s, errno:%{public}d", realPath.c_str(), errno); 90 return ERR_APPEXECFWK_INSTALL_INVALID_BUNDLE_FILE; 91 } 92 if (!CheckFileSize(realPath, MAX_HAP_SIZE)) { 93 APP_LOGE("file size larger than max hap size Max size is: %{public}" PRId64, MAX_HAP_SIZE); 94 return ERR_APPEXECFWK_INSTALL_INVALID_HAP_SIZE; 95 } 96 return ERR_OK; 97 } 98 CheckFilePath(const std::vector<std::string> & bundlePaths,std::vector<std::string> & realPaths)99 ErrCode BundleUtil::CheckFilePath(const std::vector<std::string> &bundlePaths, std::vector<std::string> &realPaths) 100 { 101 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); 102 // there are three cases for bundlePaths: 103 // 1. one bundle direction in the bundlePaths, some hap files under this bundle direction. 104 // 2. one hap direction in the bundlePaths. 105 // 3. some hap file directions in the bundlePaths. 106 APP_LOGD("check file path"); 107 if (bundlePaths.empty()) { 108 APP_LOGE("bundle file paths invalid"); 109 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID; 110 } 111 ErrCode ret = ERR_OK; 112 113 if (bundlePaths.size() == 1) { 114 struct stat s; 115 std::string bundlePath = bundlePaths.front(); 116 if (stat(bundlePath.c_str(), &s) == 0) { 117 std::string realPath = ""; 118 // it is a direction 119 if ((s.st_mode & S_IFDIR) && !GetHapFilesFromBundlePath(bundlePath, realPaths)) { 120 APP_LOGE("GetHapFilesFromBundlePath failed with bundlePath:%{public}s", bundlePaths.front().c_str()); 121 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID; 122 } 123 // it is a file 124 if ((s.st_mode & S_IFREG) && (ret = CheckFilePath(bundlePaths.front(), realPath)) == ERR_OK) { 125 realPaths.emplace_back(realPath); 126 } 127 return ret; 128 } else { 129 APP_LOGE("bundlePath not existed with :%{public}s errno %{public}d", bundlePaths.front().c_str(), errno); 130 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID; 131 } 132 } else { 133 for (const std::string& bundlePath : bundlePaths) { 134 std::string realPath = ""; 135 ret = CheckFilePath(bundlePath, realPath); 136 if (ret != ERR_OK) { 137 return ret; 138 } 139 realPaths.emplace_back(realPath); 140 } 141 } 142 APP_LOGD("finish check file path"); 143 return ret; 144 } 145 CheckFileType(const std::string & fileName,const std::string & extensionName)146 bool BundleUtil::CheckFileType(const std::string &fileName, const std::string &extensionName) 147 { 148 APP_LOGD("path is %{public}s, support suffix is %{public}s", fileName.c_str(), extensionName.c_str()); 149 if (!CheckFileName(fileName)) { 150 return false; 151 } 152 153 auto position = fileName.rfind('.'); 154 if (position == std::string::npos) { 155 APP_LOGE("filename no extension name"); 156 return false; 157 } 158 159 std::string suffixStr = fileName.substr(position); 160 return LowerStr(suffixStr) == extensionName; 161 } 162 CheckFileName(const std::string & fileName)163 bool BundleUtil::CheckFileName(const std::string &fileName) 164 { 165 if (fileName.empty()) { 166 APP_LOGE("the file name is empty"); 167 return false; 168 } 169 if (fileName.size() > ServiceConstants::PATH_MAX_SIZE) { 170 APP_LOGE("bundle file path length %{public}zu too long", fileName.size()); 171 return false; 172 } 173 return true; 174 } 175 CheckFileSize(const std::string & bundlePath,const int64_t fileSize)176 bool BundleUtil::CheckFileSize(const std::string &bundlePath, const int64_t fileSize) 177 { 178 APP_LOGD("fileSize is %{public}" PRId64, fileSize); 179 struct stat fileInfo = { 0 }; 180 if (stat(bundlePath.c_str(), &fileInfo) != 0) { 181 APP_LOGE("call stat error:%{public}d", errno); 182 return false; 183 } 184 if (fileInfo.st_size > fileSize) { 185 return false; 186 } 187 return true; 188 } 189 CheckSystemSize(const std::string & bundlePath,const std::string & diskPath)190 bool BundleUtil::CheckSystemSize(const std::string &bundlePath, const std::string &diskPath) 191 { 192 struct statfs diskInfo = { 0 }; 193 if (statfs(diskPath.c_str(), &diskInfo) != 0) { 194 APP_LOGE("call statfs error:%{public}d", errno); 195 return false; 196 } 197 int64_t freeSize = static_cast<int64_t>(diskInfo.f_bavail * diskInfo.f_bsize); 198 APP_LOGD("left free size in the disk path is %{public}" PRId64, freeSize); 199 struct stat fileInfo = { 0 }; 200 if (stat(bundlePath.c_str(), &fileInfo) != 0) { 201 APP_LOGE("call stat error:%{public}d", errno); 202 return false; 203 } 204 if (std::max(fileInfo.st_size * SPACE_NEED_DOUBLE, HALF_GB) > freeSize) { 205 return false; 206 } 207 return true; 208 } 209 CheckSystemFreeSize(const std::string & path,int64_t size)210 bool BundleUtil::CheckSystemFreeSize(const std::string &path, int64_t size) 211 { 212 struct statfs diskInfo = { 0 }; 213 if (statfs(path.c_str(), &diskInfo) != 0) { 214 APP_LOGE("call statfs error:%{public}d", errno); 215 return false; 216 } 217 int64_t freeSize = static_cast<int64_t>(diskInfo.f_bavail * diskInfo.f_bsize); 218 return freeSize >= size; 219 } 220 CheckSystemSizeAndHisysEvent(const std::string & path,const std::string & fileName)221 bool BundleUtil::CheckSystemSizeAndHisysEvent(const std::string &path, const std::string &fileName) 222 { 223 struct statfs diskInfo = { 0 }; 224 if (statfs(path.c_str(), &diskInfo) != 0) { 225 APP_LOGE("call statfs error:%{public}d", errno); 226 return false; 227 } 228 int64_t freeSize = static_cast<int64_t>(diskInfo.f_bavail * diskInfo.f_bsize); 229 return freeSize < DISK_REMAINING_SIZE_LIMIT; 230 } 231 GetHapFilesFromBundlePath(const std::string & currentBundlePath,std::vector<std::string> & hapFileList)232 bool BundleUtil::GetHapFilesFromBundlePath(const std::string& currentBundlePath, std::vector<std::string>& hapFileList) 233 { 234 APP_LOGD("GetHapFilesFromBundlePath with path is %{public}s", currentBundlePath.c_str()); 235 if (currentBundlePath.empty()) { 236 return false; 237 } 238 DIR* dir = opendir(currentBundlePath.c_str()); 239 if (dir == nullptr) { 240 char errMsg[256] = {0}; 241 strerror_r(errno, errMsg, sizeof(errMsg)); 242 APP_LOGE("GetHapFilesFromBundlePath open bundle dir:%{public}s failed due to %{public}s, errno:%{public}d", 243 currentBundlePath.c_str(), errMsg, errno); 244 return false; 245 } 246 std::string bundlePath = currentBundlePath; 247 if (bundlePath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) { 248 bundlePath.append(ServiceConstants::PATH_SEPARATOR); 249 } 250 struct dirent *entry = nullptr; 251 while ((entry = readdir(dir)) != nullptr) { 252 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { 253 continue; 254 } 255 const std::string hapFilePath = bundlePath + entry->d_name; 256 std::string realPath = ""; 257 if (CheckFilePath(hapFilePath, realPath) != ERR_OK) { 258 APP_LOGE("find invalid hap path %{public}s", hapFilePath.c_str()); 259 closedir(dir); 260 return false; 261 } 262 hapFileList.emplace_back(realPath); 263 APP_LOGD("find hap path %{public}s", realPath.c_str()); 264 265 if (!hapFileList.empty() && (hapFileList.size() > ServiceConstants::MAX_HAP_NUMBER)) { 266 APP_LOGE("reach the max hap number 128, stop to add more"); 267 closedir(dir); 268 return false; 269 } 270 } 271 closedir(dir); 272 return true; 273 } 274 GetCurrentTime()275 int64_t BundleUtil::GetCurrentTime() 276 { 277 int64_t time = 278 std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()) 279 .count(); 280 APP_LOGD("the current time in seconds is %{public}" PRId64, time); 281 return time; 282 } 283 GetCurrentTimeMs()284 int64_t BundleUtil::GetCurrentTimeMs() 285 { 286 int64_t time = 287 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()) 288 .count(); 289 APP_LOGD("the current time in milliseconds is %{public}" PRId64, time); 290 return time; 291 } 292 GetCurrentTimeNs()293 int64_t BundleUtil::GetCurrentTimeNs() 294 { 295 int64_t time = 296 std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()) 297 .count(); 298 APP_LOGD("the current time in nanoseconds is %{public}" PRId64, time); 299 return time; 300 } 301 DeviceAndNameToKey(const std::string & deviceId,const std::string & bundleName,std::string & key)302 void BundleUtil::DeviceAndNameToKey( 303 const std::string &deviceId, const std::string &bundleName, std::string &key) 304 { 305 key.append(deviceId); 306 key.append(Constants::FILE_UNDERLINE); 307 key.append(bundleName); 308 APP_LOGD("bundleName = %{public}s", bundleName.c_str()); 309 } 310 KeyToDeviceAndName(const std::string & key,std::string & deviceId,std::string & bundleName)311 bool BundleUtil::KeyToDeviceAndName( 312 const std::string &key, std::string &deviceId, std::string &bundleName) 313 { 314 bool ret = false; 315 std::vector<std::string> splitStrs; 316 OHOS::SplitStr(key, Constants::FILE_UNDERLINE, splitStrs); 317 // the expect split size should be 2. 318 // key rule is <deviceId>_<bundleName> 319 if (splitStrs.size() == EXPECT_SPLIT_SIZE) { 320 deviceId = splitStrs[0]; 321 bundleName = splitStrs[1]; 322 ret = true; 323 } 324 APP_LOGD("bundleName = %{public}s", bundleName.c_str()); 325 return ret; 326 } 327 GetUserIdByCallingUid()328 int32_t BundleUtil::GetUserIdByCallingUid() 329 { 330 int32_t uid = IPCSkeleton::GetCallingUid(); 331 APP_LOGD("get calling uid(%{public}d)", uid); 332 return GetUserIdByUid(uid); 333 } 334 GetUserIdByUid(int32_t uid)335 int32_t BundleUtil::GetUserIdByUid(int32_t uid) 336 { 337 if (uid <= Constants::INVALID_UID) { 338 APP_LOGE("uid illegal: %{public}d", uid); 339 return Constants::INVALID_USERID; 340 } 341 342 return uid / Constants::BASE_USER_RANGE; 343 } 344 MakeFsConfig(const std::string & bundleName,int32_t bundleId,const std::string & configPath)345 void BundleUtil::MakeFsConfig(const std::string &bundleName, int32_t bundleId, const std::string &configPath) 346 { 347 std::string bundleDir = configPath + ServiceConstants::PATH_SEPARATOR + bundleName; 348 if (access(bundleDir.c_str(), F_OK) != 0) { 349 APP_LOGD("fail to access error:%{public}d", errno); 350 if (mkdir(bundleDir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { 351 APP_LOGE("make bundle dir error:%{public}d", errno); 352 return; 353 } 354 } 355 356 std::string realBundleDir; 357 if (!PathToRealPath(bundleDir, realBundleDir)) { 358 APP_LOGE("bundleIdFile is not real path"); 359 return; 360 } 361 362 realBundleDir += (ServiceConstants::PATH_SEPARATOR + BUNDLE_ID_FILE); 363 364 int32_t bundleIdFd = open(realBundleDir.c_str(), O_WRONLY | O_TRUNC); 365 if (bundleIdFd > 0) { 366 std::string bundleIdStr = std::to_string(bundleId); 367 if (write(bundleIdFd, bundleIdStr.c_str(), bundleIdStr.size()) < 0) { 368 APP_LOGE("write bundleId error:%{public}d", errno); 369 } 370 } 371 close(bundleIdFd); 372 } 373 RemoveFsConfig(const std::string & bundleName,const std::string & configPath)374 void BundleUtil::RemoveFsConfig(const std::string &bundleName, const std::string &configPath) 375 { 376 std::string bundleDir = configPath + ServiceConstants::PATH_SEPARATOR + bundleName; 377 std::string realBundleDir; 378 if (!PathToRealPath(bundleDir, realBundleDir)) { 379 APP_LOGE("bundleDir is not real path"); 380 return; 381 } 382 if (rmdir(realBundleDir.c_str()) != 0) { 383 APP_LOGE("remove hmdfs bundle dir error:%{public}d", errno); 384 } 385 } 386 CreateTempDir(const std::string & tempDir)387 std::string BundleUtil::CreateTempDir(const std::string &tempDir) 388 { 389 if (!OHOS::ForceCreateDirectory(tempDir)) { 390 APP_LOGE("mkdir %{public}s failed", tempDir.c_str()); 391 return ""; 392 } 393 if (chown(tempDir.c_str(), Constants::FOUNDATION_UID, ServiceConstants::BMS_GID) != 0) { 394 APP_LOGE("fail to change %{public}s ownership errno:%{public}d", tempDir.c_str(), errno); 395 return ""; 396 } 397 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 398 if (!OHOS::ChangeModeFile(tempDir, mode)) { 399 APP_LOGE("change mode failed, temp install dir : %{public}s", tempDir.c_str()); 400 return ""; 401 } 402 return tempDir; 403 } 404 CreateInstallTempDir(uint32_t installerId,const DirType & type)405 std::string BundleUtil::CreateInstallTempDir(uint32_t installerId, const DirType &type) 406 { 407 std::time_t curTime = std::time(0); 408 std::string tempDir = ServiceConstants::HAP_COPY_PATH; 409 if (type == DirType::STREAM_INSTALL_DIR) { 410 tempDir += ServiceConstants::PATH_SEPARATOR + ServiceConstants::STREAM_INSTALL_PATH; 411 } else if (type == DirType::QUICK_FIX_DIR) { 412 tempDir += ServiceConstants::PATH_SEPARATOR + ServiceConstants::QUICK_FIX_PATH; 413 } else if (type == DirType::SIG_FILE_DIR) { 414 tempDir += ServiceConstants::PATH_SEPARATOR + ServiceConstants::SIGNATURE_FILE_PATH; 415 } else if (type == DirType::PGO_FILE_DIR) { 416 tempDir += ServiceConstants::PATH_SEPARATOR + PGO_FILE_PATH; 417 } else if (type == DirType::ABC_FILE_DIR) { 418 tempDir += ServiceConstants::PATH_SEPARATOR + ABC_FILE_PATH; 419 } else if (type == DirType::EXT_RESOURCE_FILE_DIR) { 420 tempDir += ServiceConstants::PATH_SEPARATOR + ServiceConstants::EXT_RESOURCE_FILE_PATH; 421 } else { 422 return ""; 423 } 424 425 if (CreateTempDir(tempDir).empty()) { 426 APP_LOGE("create tempDir failed"); 427 return ""; 428 } 429 430 tempDir += ServiceConstants::PATH_SEPARATOR + std::to_string(curTime) + 431 std::to_string(installerId) + ServiceConstants::PATH_SEPARATOR; 432 return CreateTempDir(tempDir); 433 } 434 CreateSharedBundleTempDir(uint32_t installerId,uint32_t index)435 std::string BundleUtil::CreateSharedBundleTempDir(uint32_t installerId, uint32_t index) 436 { 437 std::time_t curTime = std::time(0); 438 std::string tempDir = ServiceConstants::HAP_COPY_PATH; 439 tempDir += ServiceConstants::PATH_SEPARATOR + ServiceConstants::STREAM_INSTALL_PATH; 440 tempDir += ServiceConstants::PATH_SEPARATOR + std::to_string(curTime) + std::to_string(installerId) 441 + Constants::FILE_UNDERLINE + std::to_string(index)+ ServiceConstants::PATH_SEPARATOR; 442 return CreateTempDir(tempDir); 443 } 444 CreateFileDescriptor(const std::string & bundlePath,long long offset)445 int32_t BundleUtil::CreateFileDescriptor(const std::string &bundlePath, long long offset) 446 { 447 int fd = -1; 448 if (bundlePath.length() > ServiceConstants::PATH_MAX_SIZE) { 449 APP_LOGE("the length of the bundlePath exceeds maximum limitation"); 450 return fd; 451 } 452 if ((fd = open(bundlePath.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) { 453 APP_LOGE("open bundlePath %{public}s failed errno:%{public}d", bundlePath.c_str(), errno); 454 return fd; 455 } 456 if (offset > 0) { 457 lseek(fd, offset, SEEK_SET); 458 } 459 return fd; 460 } 461 CreateFileDescriptorForReadOnly(const std::string & bundlePath,long long offset)462 int32_t BundleUtil::CreateFileDescriptorForReadOnly(const std::string &bundlePath, long long offset) 463 { 464 int fd = -1; 465 if (bundlePath.length() > ServiceConstants::PATH_MAX_SIZE) { 466 APP_LOGE("the length of the bundlePath exceeds maximum limitation"); 467 return fd; 468 } 469 std::string realPath; 470 if (!PathToRealPath(bundlePath, realPath)) { 471 APP_LOGE("file is not real path"); 472 return fd; 473 } 474 475 if ((fd = open(realPath.c_str(), O_RDONLY)) < 0) { 476 APP_LOGE("open bundlePath %{public}s failed errno:%{public}d", realPath.c_str(), errno); 477 return fd; 478 } 479 if (offset > 0) { 480 lseek(fd, offset, SEEK_SET); 481 } 482 return fd; 483 } 484 CloseFileDescriptor(std::vector<int32_t> & fdVec)485 void BundleUtil::CloseFileDescriptor(std::vector<int32_t> &fdVec) 486 { 487 for_each(fdVec.begin(), fdVec.end(), [](const auto &fd) { 488 if (fd > 0) { 489 close(fd); 490 } 491 }); 492 fdVec.clear(); 493 } 494 IsExistFile(const std::string & path)495 bool BundleUtil::IsExistFile(const std::string &path) 496 { 497 if (path.empty()) { 498 return false; 499 } 500 501 struct stat buf = {}; 502 if (stat(path.c_str(), &buf) != 0) { 503 APP_LOGE("fail stat errno:%{public}d", errno); 504 return false; 505 } 506 507 return S_ISREG(buf.st_mode); 508 } 509 IsExistFileNoLog(const std::string & path)510 bool BundleUtil::IsExistFileNoLog(const std::string &path) 511 { 512 if (path.empty()) { 513 return false; 514 } 515 516 struct stat buf = {}; 517 if (stat(path.c_str(), &buf) != 0) { 518 return false; 519 } 520 521 return S_ISREG(buf.st_mode); 522 } 523 IsExistDir(const std::string & path)524 bool BundleUtil::IsExistDir(const std::string &path) 525 { 526 if (path.empty()) { 527 return false; 528 } 529 530 struct stat buf = {}; 531 if (stat(path.c_str(), &buf) != 0) { 532 APP_LOGE("fail stat errno:%{public}d", errno); 533 return false; 534 } 535 536 return S_ISDIR(buf.st_mode); 537 } 538 IsExistDirNoLog(const std::string & path)539 bool BundleUtil::IsExistDirNoLog(const std::string &path) 540 { 541 if (path.empty()) { 542 return false; 543 } 544 545 struct stat buf = {}; 546 if (stat(path.c_str(), &buf) != 0) { 547 return false; 548 } 549 550 return S_ISDIR(buf.st_mode); 551 } 552 IsPathInformationConsistent(const std::string & path,int32_t uid,int32_t gid)553 bool BundleUtil::IsPathInformationConsistent(const std::string &path, int32_t uid, int32_t gid) 554 { 555 if (path.empty()) { 556 return false; 557 } 558 struct stat buf = {}; 559 if (stat(path.c_str(), &buf) != 0) { 560 return false; 561 } 562 if ((static_cast<int32_t>(buf.st_uid) != uid) || ((static_cast<int32_t>(buf.st_gid) != gid))) { 563 APP_LOGE("path uid or gid is not same"); 564 return false; 565 } 566 return true; 567 } 568 CalculateFileSize(const std::string & bundlePath)569 int64_t BundleUtil::CalculateFileSize(const std::string &bundlePath) 570 { 571 struct stat fileInfo = { 0 }; 572 if (stat(bundlePath.c_str(), &fileInfo) != 0) { 573 APP_LOGE("call stat error:%{public}d", errno); 574 return 0; 575 } 576 577 return static_cast<int64_t>(fileInfo.st_size); 578 } 579 RenameFile(const std::string & oldPath,const std::string & newPath)580 bool BundleUtil::RenameFile(const std::string &oldPath, const std::string &newPath) 581 { 582 if (oldPath.empty() || newPath.empty()) { 583 APP_LOGE("oldPath or newPath is empty"); 584 return false; 585 } 586 587 if (!DeleteDir(newPath)) { 588 APP_LOGE("delete newPath failed"); 589 return false; 590 } 591 592 return rename(oldPath.c_str(), newPath.c_str()) == 0; 593 } 594 DeleteDir(const std::string & path)595 bool BundleUtil::DeleteDir(const std::string &path) 596 { 597 if (IsExistFile(path)) { 598 return OHOS::RemoveFile(path); 599 } 600 601 if (IsExistDir(path)) { 602 return OHOS::ForceRemoveDirectory(path); 603 } 604 605 return true; 606 } 607 IsUtd(const std::string & param)608 bool BundleUtil::IsUtd(const std::string ¶m) 609 { 610 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED 611 bool isUtd = false; 612 auto ret = UDMF::UtdClient::GetInstance().IsUtd(param, isUtd); 613 return ret == ERR_OK && isUtd; 614 #else 615 return false; 616 #endif 617 } 618 IsSpecificUtd(const std::string & param)619 bool BundleUtil::IsSpecificUtd(const std::string ¶m) 620 { 621 if (!IsUtd(param)) { 622 return false; 623 } 624 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED 625 std::shared_ptr<UDMF::TypeDescriptor> typeDescriptor; 626 auto ret = UDMF::UtdClient::GetInstance().GetTypeDescriptor(param, typeDescriptor); 627 if (ret != ERR_OK || typeDescriptor == nullptr) { 628 return false; 629 } 630 std::vector<std::string> mimeTypes = typeDescriptor->GetMimeTypes(); 631 std::vector<std::string> filenameExtensions = typeDescriptor->GetFilenameExtensions(); 632 return !mimeTypes.empty() || !filenameExtensions.empty(); 633 #else 634 return false; 635 #endif 636 } 637 GetUtdVectorByMimeType(const std::string & mimeType)638 std::vector<std::string> BundleUtil::GetUtdVectorByMimeType(const std::string &mimeType) 639 { 640 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED 641 std::vector<std::string> utdVector; 642 auto ret = UDMF::UtdClient::GetInstance().GetUniformDataTypesByMIMEType(mimeType, utdVector); 643 if (ret != ERR_OK || utdVector.empty()) { 644 return {}; 645 } 646 return utdVector; 647 #else 648 return {}; 649 #endif 650 } 651 GetBoolStrVal(bool val)652 std::string BundleUtil::GetBoolStrVal(bool val) 653 { 654 return val ? "true" : "false"; 655 } 656 CopyFile(const std::string & sourceFile,const std::string & destinationFile)657 bool BundleUtil::CopyFile( 658 const std::string &sourceFile, const std::string &destinationFile) 659 { 660 if (sourceFile.empty() || destinationFile.empty()) { 661 APP_LOGE("Copy file failed due to sourceFile or destinationFile is empty"); 662 return false; 663 } 664 665 std::ifstream in(sourceFile); 666 if (!in.is_open()) { 667 APP_LOGE("Copy file failed due to open sourceFile failed errno:%{public}d", errno); 668 return false; 669 } 670 671 std::ofstream out(destinationFile); 672 if (!out.is_open()) { 673 APP_LOGE("Copy file failed due to open destinationFile failed errno:%{public}d", errno); 674 in.close(); 675 return false; 676 } 677 678 out << in.rdbuf(); 679 in.close(); 680 out.close(); 681 return true; 682 } 683 CopyFileFast(const std::string & sourcePath,const std::string & destPath)684 bool BundleUtil::CopyFileFast(const std::string &sourcePath, const std::string &destPath) 685 { 686 APP_LOGI("sourcePath : %{public}s, destPath : %{public}s", sourcePath.c_str(), destPath.c_str()); 687 if (sourcePath.empty() || destPath.empty()) { 688 APP_LOGE("invalid path"); 689 return false; 690 } 691 692 int32_t sourceFd = open(sourcePath.c_str(), O_RDONLY); 693 if (sourceFd == -1) { 694 APP_LOGE("sourcePath open failed, errno : %{public}d", errno); 695 return CopyFile(sourcePath, destPath); 696 } 697 698 struct stat sourceStat; 699 if (fstat(sourceFd, &sourceStat) == -1) { 700 APP_LOGE("fstat failed, errno : %{public}d", errno); 701 close(sourceFd); 702 return CopyFile(sourcePath, destPath); 703 } 704 if (sourceStat.st_size < 0) { 705 APP_LOGE("invalid st_size"); 706 close(sourceFd); 707 return CopyFile(sourcePath, destPath); 708 } 709 710 int32_t destFd = open( 711 destPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 712 if (destFd == -1) { 713 APP_LOGE("destPath open failed, errno : %{public}d", errno); 714 close(sourceFd); 715 return CopyFile(sourcePath, destPath); 716 } 717 718 size_t buffer = 524288; // 0.5M 719 size_t transferCount = 0; 720 ssize_t singleTransfer = 0; 721 while ((singleTransfer = sendfile(destFd, sourceFd, nullptr, buffer)) > 0) { 722 transferCount += static_cast<size_t>(singleTransfer); 723 } 724 725 if (singleTransfer == -1 || transferCount != static_cast<size_t>(sourceStat.st_size)) { 726 APP_LOGE("sendfile failed, errno : %{public}d, send count : %{public}zu , file size : %{public}zu", 727 errno, transferCount, static_cast<size_t>(sourceStat.st_size)); 728 close(sourceFd); 729 close(destFd); 730 return CopyFile(sourcePath, destPath); 731 } 732 733 close(sourceFd); 734 close(destFd); 735 APP_LOGD("sendfile success"); 736 return true; 737 } 738 GetResource(const std::string & bundleName,const std::string & moduleName,uint32_t resId)739 Resource BundleUtil::GetResource(const std::string &bundleName, const std::string &moduleName, uint32_t resId) 740 { 741 Resource resource; 742 resource.bundleName = bundleName; 743 resource.moduleName = moduleName; 744 resource.id = resId; 745 return resource; 746 } 747 CreateDir(const std::string & dir)748 bool BundleUtil::CreateDir(const std::string &dir) 749 { 750 if (dir.empty()) { 751 APP_LOGE("path is empty"); 752 return false; 753 } 754 755 if (IsExistFile(dir)) { 756 return true; 757 } 758 759 if (!OHOS::ForceCreateDirectory(dir)) { 760 APP_LOGE("mkdir %{public}s failed", dir.c_str()); 761 return false; 762 } 763 764 if (chown(dir.c_str(), Constants::FOUNDATION_UID, ServiceConstants::BMS_GID) != 0) { 765 APP_LOGE("fail change %{public}s ownership, errno:%{public}d", dir.c_str(), errno); 766 return false; 767 } 768 769 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 770 if (!OHOS::ChangeModeFile(dir, mode)) { 771 APP_LOGE("change mode failed, temp install dir : %{public}s", dir.c_str()); 772 return false; 773 } 774 return true; 775 } 776 RevertToRealPath(const std::string & sandBoxPath,const std::string & bundleName,std::string & realPath)777 bool BundleUtil::RevertToRealPath(const std::string &sandBoxPath, const std::string &bundleName, std::string &realPath) 778 { 779 if (sandBoxPath.empty() || bundleName.empty() || 780 (sandBoxPath.find(ServiceConstants::SANDBOX_DATA_PATH) == std::string::npos && 781 sandBoxPath.find(ServiceConstants::APP_INSTALL_SANDBOX_PATH) == std::string::npos)) { 782 APP_LOGE("input sandboxPath or bundleName invalid"); 783 return false; 784 } 785 786 realPath = sandBoxPath; 787 if (sandBoxPath.find(ServiceConstants::SANDBOX_DATA_PATH) == 0) { 788 std::string relaDataPath = std::string(ServiceConstants::REAL_DATA_PATH) + ServiceConstants::PATH_SEPARATOR 789 + std::to_string(BundleUtil::GetUserIdByCallingUid()) + ServiceConstants::BASE + bundleName; 790 realPath.replace(realPath.find(ServiceConstants::SANDBOX_DATA_PATH), 791 std::string(ServiceConstants::SANDBOX_DATA_PATH).size(), relaDataPath); 792 } else if (sandBoxPath.find(ServiceConstants::APP_INSTALL_SANDBOX_PATH) == 0) { 793 std::string relaDataPath = std::string(ServiceConstants::BUNDLE_MANAGER_SERVICE_PATH) + 794 ServiceConstants::GALLERY_DOWNLOAD_PATH + std::to_string(BundleUtil::GetUserIdByCallingUid()); 795 realPath.replace(realPath.find(ServiceConstants::APP_INSTALL_SANDBOX_PATH), 796 std::string(ServiceConstants::APP_INSTALL_SANDBOX_PATH).size(), relaDataPath); 797 } else { 798 APP_LOGE("input sandboxPath invalid"); 799 return false; 800 } 801 return true; 802 } 803 StartWith(const std::string & source,const std::string & prefix)804 bool BundleUtil::StartWith(const std::string &source, const std::string &prefix) 805 { 806 if (source.empty() || prefix.empty()) { 807 return false; 808 } 809 810 return source.find(prefix) == 0; 811 } 812 EndWith(const std::string & source,const std::string & suffix)813 bool BundleUtil::EndWith(const std::string &source, const std::string &suffix) 814 { 815 if (source.empty() || suffix.empty()) { 816 return false; 817 } 818 819 auto position = source.rfind(suffix); 820 if (position == std::string::npos) { 821 return false; 822 } 823 824 std::string suffixStr = source.substr(position); 825 return suffixStr == suffix; 826 } 827 GetFileSize(const std::string & filePath)828 int64_t BundleUtil::GetFileSize(const std::string &filePath) 829 { 830 struct stat fileInfo = { 0 }; 831 if (stat(filePath.c_str(), &fileInfo) != 0) { 832 APP_LOGE("call stat error:%{public}d", errno); 833 return 0; 834 } 835 return fileInfo.st_size; 836 } 837 CopyFileToSecurityDir(const std::string & filePath,const DirType & dirType,std::vector<std::string> & toDeletePaths,bool rename)838 std::string BundleUtil::CopyFileToSecurityDir(const std::string &filePath, const DirType &dirType, 839 std::vector<std::string> &toDeletePaths, bool rename) 840 { 841 APP_LOGD("the original dir is %{public}s", filePath.c_str()); 842 std::string destination = ""; 843 std::string subStr = ""; 844 destination.append(ServiceConstants::HAP_COPY_PATH).append(ServiceConstants::PATH_SEPARATOR); 845 if (dirType == DirType::STREAM_INSTALL_DIR) { 846 subStr = ServiceConstants::STREAM_INSTALL_PATH; 847 destination.append(ServiceConstants::SECURITY_STREAM_INSTALL_PATH); 848 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 849 if (InstalldClient::GetInstance()->Mkdir( 850 destination, mode, Constants::FOUNDATION_UID, ServiceConstants::BMS_GID) != ERR_OK) { 851 APP_LOGW("installd mkdir %{private}s failed", destination.c_str()); 852 } 853 } 854 if (dirType == DirType::SIG_FILE_DIR) { 855 subStr = ServiceConstants::SIGNATURE_FILE_PATH; 856 destination.append(ServiceConstants::SECURITY_SIGNATURE_FILE_PATH); 857 } 858 destination.append(ServiceConstants::PATH_SEPARATOR).append(std::to_string(GetCurrentTimeNs())); 859 destination = CreateTempDir(destination); 860 auto pos = filePath.find(subStr); 861 if (pos == std::string::npos) { // this circumstance could not be considered laterly 862 auto lastPathSeperator = filePath.rfind(ServiceConstants::PATH_SEPARATOR); 863 if ((lastPathSeperator != std::string::npos) && (lastPathSeperator != filePath.length() - 1)) { 864 toDeletePaths.emplace_back(destination); 865 destination.append(filePath.substr(lastPathSeperator)); 866 } 867 } else { 868 auto secondLastPathSep = filePath.find(ServiceConstants::PATH_SEPARATOR, pos); 869 if ((secondLastPathSep == std::string::npos) || (secondLastPathSep == filePath.length() - 1)) { 870 return ""; 871 } 872 auto thirdLastPathSep = 873 filePath.find(ServiceConstants::PATH_SEPARATOR, secondLastPathSep + 1); 874 if ((thirdLastPathSep == std::string::npos) || (thirdLastPathSep == filePath.length() - 1)) { 875 return ""; 876 } 877 toDeletePaths.emplace_back(destination); 878 std::string innerSubstr = 879 filePath.substr(secondLastPathSep, thirdLastPathSep - secondLastPathSep + 1); 880 destination = CreateTempDir(destination.append(innerSubstr)); 881 destination.append(filePath.substr(thirdLastPathSep + 1)); 882 } 883 APP_LOGD("the destination dir is %{public}s", destination.c_str()); 884 if (destination.empty()) { 885 return ""; 886 } 887 if (rename) { 888 APP_LOGD("rename file from %{public}s to %{public}s", filePath.c_str(), destination.c_str()); 889 if (!RenameFile(filePath, destination)) { 890 APP_LOGE("rename file from %{public}s to %{public}s failed", filePath.c_str(), destination.c_str()); 891 return ""; 892 } 893 } else { 894 if (!CopyFileFast(filePath, destination)) { 895 APP_LOGE("copy file from %{public}s to %{public}s failed", filePath.c_str(), destination.c_str()); 896 return ""; 897 } 898 } 899 return destination; 900 } 901 DeleteTempDirs(const std::vector<std::string> & tempDirs)902 void BundleUtil::DeleteTempDirs(const std::vector<std::string> &tempDirs) 903 { 904 for (const auto &tempDir : tempDirs) { 905 APP_LOGD("the temp hap dir %{public}s needs to be deleted", tempDir.c_str()); 906 BundleUtil::DeleteDir(tempDir); 907 } 908 } 909 GetHexHash(const std::string & s)910 std::string BundleUtil::GetHexHash(const std::string &s) 911 { 912 std::hash<std::string> hasher; 913 size_t hash = hasher(s); 914 915 std::stringstream ss; 916 ss << std::hex << hash; 917 918 std::string hash_str = ss.str(); 919 return hash_str; 920 } 921 RecursiveHash(std::string & s)922 void BundleUtil::RecursiveHash(std::string& s) 923 { 924 if (s.size() >= ORIGIN_STRING_LENGTH) { 925 s = s.substr(s.size() - ORIGIN_STRING_LENGTH); 926 return; 927 } 928 std::string hash = GetHexHash(s); 929 s += hash; 930 RecursiveHash(s); 931 } 932 GenerateUuid()933 std::string BundleUtil::GenerateUuid() 934 { 935 std::lock_guard<std::mutex> lock(g_mutex); 936 auto currentTime = std::chrono::system_clock::now(); 937 auto timestampNanoseconds = 938 std::chrono::duration_cast<std::chrono::nanoseconds>(currentTime.time_since_epoch()).count(); 939 940 // convert nanosecond timestamps to string 941 std::string s = std::to_string(timestampNanoseconds); 942 std::string timeStr = GetHexHash(s); 943 944 char deviceId[UUID_LENGTH_MAX] = { 0 }; 945 auto ret = GetDevUdid(deviceId, UUID_LENGTH_MAX); 946 std::string deviceUdid; 947 std::string deviceStr; 948 if (ret != 0) { 949 APP_LOGW("GetDevUdid failed"); 950 } else { 951 deviceUdid = std::string{ deviceId }; 952 deviceStr = GetHexHash(deviceUdid); 953 } 954 955 std::string uuid = timeStr + deviceStr; 956 RecursiveHash(uuid); 957 958 for (int32_t index : SEPARATOR_POSITIONS) { 959 uuid.insert(index, 1, UUID_SEPARATOR); 960 } 961 return uuid; 962 } 963 GenerateUuidByKey(const std::string & key)964 std::string BundleUtil::GenerateUuidByKey(const std::string &key) 965 { 966 std::string keyHash = GetHexHash(key); 967 968 char deviceId[UUID_LENGTH_MAX] = { 0 }; 969 auto ret = GetDevUdid(deviceId, UUID_LENGTH_MAX); 970 std::string deviceUdid; 971 std::string deviceStr; 972 if (ret != 0) { 973 APP_LOGW("GetDevUdid failed"); 974 } else { 975 deviceUdid = std::string{ deviceId }; 976 deviceStr = GetHexHash(deviceUdid); 977 } 978 979 std::string uuid = keyHash + deviceStr; 980 RecursiveHash(uuid); 981 982 for (int32_t index : SEPARATOR_POSITIONS) { 983 uuid.insert(index, 1, UUID_SEPARATOR); 984 } 985 return uuid; 986 } 987 ExtractGroupIdByDevelopId(const std::string & developerId)988 std::string BundleUtil::ExtractGroupIdByDevelopId(const std::string &developerId) 989 { 990 std::string::size_type dot_position = developerId.find('.'); 991 if (dot_position == std::string::npos) { 992 // If cannot find '.' , the input string is developerId, return developerId 993 return developerId; 994 } 995 if (dot_position == 0) { 996 // if'.' In the first place, then groupId is empty, return developerId 997 return developerId.substr(1); 998 } 999 // If '.' If it is not the first place, there is a groupId, and the groupId is returned 1000 return developerId.substr(0, dot_position); 1001 } 1002 ToString(const std::vector<std::string> & vector)1003 std::string BundleUtil::ToString(const std::vector<std::string> &vector) 1004 { 1005 std::string ret; 1006 for (const std::string &item : vector) { 1007 ret.append(item).append(","); 1008 } 1009 return ret; 1010 } 1011 GetNoDisablingConfigPath()1012 std::string BundleUtil::GetNoDisablingConfigPath() 1013 { 1014 #ifdef CONFIG_POLOCY_ENABLE 1015 char buf[MAX_PATH_LEN] = { 0 }; 1016 char *configPath = GetOneCfgFile(NO_DISABLING_CONFIG_PATH, buf, MAX_PATH_LEN); 1017 if (configPath == nullptr || configPath[0] == '\0') { 1018 APP_LOGE("BundleUtil GetOneCfgFile failed"); 1019 return NO_DISABLING_CONFIG_PATH_DEFAULT; 1020 } 1021 if (strlen(configPath) > MAX_PATH_LEN) { 1022 APP_LOGE("length exceeds"); 1023 return NO_DISABLING_CONFIG_PATH_DEFAULT; 1024 } 1025 return configPath; 1026 #else 1027 return NO_DISABLING_CONFIG_PATH_DEFAULT; 1028 #endif 1029 } 1030 } // namespace AppExecFwk 1031 } // namespace OHOS 1032