1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved. 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 "common.h" 17#include <fcntl.h> 18#include <array> 19#include <cinttypes> 20#include <csignal> 21#include <dirent.h> 22#include <fstream> 23#include <iostream> 24#include <parameter.h> 25#include <parameters.h> 26#include <sstream> 27#include <sys/file.h> 28#include <sys/types.h> 29#include <sys/wait.h> 30#include <unistd.h> 31#include <sys/stat.h> 32 33#include "application_info.h" 34#include "bundle_mgr_proxy.h" 35#include "file_ex.h" 36#include "iservice_registry.h" 37#include "logging.h" 38#include "system_ability_definition.h" 39#include "os_account_info.h" 40#include "os_account_manager.h" 41 42using namespace OHOS; 43using namespace OHOS::AppExecFwk; 44namespace COMMON { 45namespace { 46const std::map<std::string, clockid_t> clockIdMap = { 47 {"realtime", CLOCK_REALTIME}, 48 {"mono", CLOCK_MONOTONIC}, 49 {"process_cputime_id", CLOCK_PROCESS_CPUTIME_ID}, 50 {"thread_cputime_id", CLOCK_THREAD_CPUTIME_ID}, 51 {"mono_raw", CLOCK_MONOTONIC_RAW}, 52 {"realtime_coarse", CLOCK_REALTIME_COARSE}, 53 {"mono_coarse", CLOCK_MONOTONIC_COARSE}, 54 {"boot", CLOCK_BOOTTIME}, 55 {"realtime_alarm", CLOCK_REALTIME_ALARM}, 56 {"boot_alarm", CLOCK_BOOTTIME_ALARM}, 57 {"sgi_cycle", CLOCK_SGI_CYCLE}, 58 {"tai", CLOCK_TAI}, 59}; 60constexpr int EXECVP_ERRNO = 2; 61const int SHELL_UID = 2000; 62const std::string DEFAULT_PATH = "/data/local/tmp/"; 63constexpr int READ = 0; 64constexpr int WRITE = 1; 65const int FILE_PATH_SIZE = 512; 66const int BUFFER_SIZE = 1024; 67const int INVALID_PID = -1; 68constexpr int32_t EC_INVALID_VALUE = -2; 69const std::string KEY_HIVIEW_USER_TYPE = "const.logsystem.versiontype"; 70const uint32_t MAX_CMD_ARGV = 50; 71const uint32_t MIN_CMD_ARGV = 2; 72const std::set<std::string> CMD_WHITE_LIST = { 73 "/system/bin/hiperf", "/system/bin/hitrace", "/system/bin/hisysevent", "/system/bin/hidumper", 74 "/system/bin/SP_daemon", "/system/bin/hiprofilerd", "/system/bin/hiprofiler_plugins", "/system/bin/native_daemon", 75 "/system/bin/hilog"}; 76} // namespace 77 78bool IsProcessRunning(int& lockFileFd) 79{ 80 setgid(SHELL_UID); 81 char buffer[PATH_MAX + 1] = {0}; 82 readlink("/proc/self/exe", buffer, PATH_MAX); 83 std::string processName = buffer; 84 int pos = static_cast<int>(processName.find_last_of('/')); 85 if (pos != 0) { 86 processName = processName.substr(pos + 1, processName.size()); 87 } 88 89 std::string fileName = DEFAULT_PATH + processName + ".pid"; 90 umask(S_IWOTH); 91 int fd = open(fileName.c_str(), O_WRONLY | O_CREAT, static_cast<mode_t>(0664)); // 0664: rw-rw-r-- 92 if (fd < 0) { 93 const int bufSize = 256; 94 char buf[bufSize] = {0}; 95 strerror_r(errno, buf, bufSize); 96 PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, fileName.c_str(), errno, buf); 97 return false; 98 } 99 int flags = fcntl(fd, F_GETFD); 100 if (flags == -1) { 101 close(fd); 102 PROFILER_LOG_ERROR(LOG_CORE, "%s: get fd flags failed!", __func__); 103 return false; 104 } 105 flags |= FD_CLOEXEC; 106 if (fcntl(fd, F_SETFD, flags) == -1) { 107 close(fd); 108 PROFILER_LOG_ERROR(LOG_CORE, "%s: set fd_cloexec failed!", __func__); 109 return false; 110 } 111 if (flock(fd, LOCK_EX | LOCK_NB) == -1) { 112 // 进程正在运行,加锁失败 113 close(fd); 114 printf("%s is running, please don't start it again.\n", processName.c_str()); 115 PROFILER_LOG_ERROR(LOG_CORE, "%s is running, please don't start it again.", processName.c_str()); 116 return true; 117 } 118 std::string pidStr = std::to_string(getpid()); 119 auto nbytes = write(fd, pidStr.data(), pidStr.size()); 120 lockFileFd = fd; 121 CHECK_TRUE(static_cast<size_t>(nbytes) == pidStr.size(), false, "write pid FAILED!"); 122 return false; 123} 124 125bool IsProcessExist(const std::string& processName, int& pid) 126{ 127 DIR* dir = opendir("/proc"); 128 CHECK_NOTNULL(dir, false, "open /proc dir failed"); 129 struct dirent* ptr; 130 int pidValue = INVALID_PID; 131 while ((ptr = readdir(dir)) != nullptr) { 132 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) { 133 continue; 134 } 135 if ((!isdigit(*ptr->d_name)) || ptr->d_type != DT_DIR) { 136 continue; 137 } 138 char filePath[FILE_PATH_SIZE] = {0}; 139 int len = snprintf_s(filePath, FILE_PATH_SIZE, FILE_PATH_SIZE - 1, "/proc/%s/cmdline", ptr->d_name); 140 if (len < 0) { 141 PROFILER_LOG_WARN(LOG_CORE, "maybe, the contents of cmdline had be cut off"); 142 continue; 143 } 144 FILE* fp = fopen(filePath, "r"); 145 if (fp == nullptr) { 146 PROFILER_LOG_DEBUG(LOG_CORE, "open file failed! %s", filePath); 147 continue; 148 } 149 char buf[BUFFER_SIZE] = {0}; 150 if (fgets(buf, sizeof(buf) - 1, fp) == nullptr) { 151 fclose(fp); 152 continue; 153 } 154 std::string str(buf); 155 size_t found = str.rfind("/"); 156 std::string fullProcess; 157 if (found != std::string::npos) { 158 fullProcess = str.substr(found + 1); 159 } else { 160 fullProcess = str; 161 } 162 if (fullProcess == processName) { 163 pidValue = atoi(ptr->d_name); 164 fclose(fp); 165 break; 166 } 167 fclose(fp); 168 } 169 closedir(dir); 170 if (pidValue != INVALID_PID) { 171 pid = pidValue; 172 } 173 return pidValue != INVALID_PID; 174} 175 176static void CloseStdio() 177{ 178 close(STDIN_FILENO); 179 close(STDOUT_FILENO); 180 close(STDERR_FILENO); 181} 182 183int StartProcess(const std::string& processBin, std::vector<char*>& argv) 184{ 185 if (argv.size() > MAX_CMD_ARGV || argv.size() < 1) { 186 PROFILER_LOG_ERROR(LOG_CORE, "%s: param invalid", __func__); 187 return -1; 188 } 189 // check whitelist 190 if (!CheckWhiteList(processBin)) { 191 PROFILER_LOG_ERROR(LOG_CORE, "%s: command not in whitelist!", __func__); 192 return -1; 193 } 194 for (auto& item : argv) { 195 std::string itemStr(item); 196 if (!CheckCmdLineArgValid(itemStr)) { 197 PROFILER_LOG_ERROR(LOG_CORE, "%s: command arg invalid : %s", __func__, itemStr.c_str()); 198 return -1; 199 } 200 } 201 int pid = fork(); 202 if (pid == 0) { 203 CloseStdio(); 204 argv.push_back(nullptr); // last item in argv must be NULL 205 int retval = execv(processBin.data(), argv.data()); 206 if (retval == -1 && errno == EXECVP_ERRNO) { 207 printf("warning: %s does not exist!\n", processBin.c_str()); 208 PROFILER_LOG_WARN(LOG_CORE, "warning: %s does not exist!", processBin.c_str()); 209 } 210 _exit(EXIT_FAILURE); 211 } 212 213 return pid; 214} 215 216int KillProcess(int pid) 217{ 218 if (pid == -1) { 219 return -1; 220 } 221 int stat; 222 kill(pid, SIGTERM); 223 if (waitpid(pid, &stat, 0) == -1) { 224 if (errno != EINTR) { 225 stat = -1; 226 } 227 } 228 return stat; 229} 230 231void PrintMallinfoLog(const std::string& mallInfoPrefix, const struct mallinfo2& mi) 232{ 233#ifdef HOOK_ENABLE 234 std::string mallinfoLog = mallInfoPrefix; 235 mallinfoLog += "arena = " + std::to_string(mi.arena) + ", ordblks = " + std::to_string(mi.ordblks); 236 mallinfoLog += ", smblks = " + std::to_string(mi.smblks) + ", hblks = " + std::to_string(mi.hblks); 237 mallinfoLog += ", hblkhd = " + std::to_string(mi.hblkhd) + ", usmblks = " + std::to_string(mi.usmblks); 238 mallinfoLog += 239 ", fsmblks = " + std::to_string(mi.fsmblks) + ", uordblks = " + std::to_string(mi.uordblks); 240 mallinfoLog += 241 ", fordblks = " + std::to_string(mi.fordblks) + ", keepcost = " + std::to_string(mi.keepcost); 242 PROFILER_LOG_INFO(LOG_CORE, "%s", mallinfoLog.c_str()); 243#endif // HOOK_ENABLE 244} 245 246bool GetDeveloperMode() 247{ 248 bool developerMode = OHOS::system::GetBoolParameter("const.security.developermode.state", true); 249 if (!developerMode) { 250 PROFILER_LOG_INFO(LOG_CORE, "It is not developer mode!"); 251 } 252 return developerMode; 253} 254 255inline int CustomFdClose(int& fd) 256{ 257 int ret = close(fd); 258 if (ret == 0) { 259 fd = -1; 260 } 261 return ret; 262} 263 264inline int CustomFdFclose(FILE** fp) 265{ 266 int ret = fclose(*fp); 267 if (ret == 0) { 268 *fp = nullptr; 269 } 270 return ret; 271} 272 273FILE* CustomPopen(const std::vector<std::string>& command, const char* type, int fds[], 274 volatile pid_t& childPid, bool needUnblock) 275{ 276 PROFILER_LOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__); 277 if (command.size() < MIN_CMD_ARGV || command.size() > MAX_CMD_ARGV || type == nullptr || strlen(type) != 1) { 278 PROFILER_LOG_ERROR(LOG_CORE, "%s: param invalid", __func__); 279 return nullptr; 280 } 281 282 // only allow "r" or "w" 283 if ((type[0] != 'r' && type[0] != 'w')) { 284 errno = EINVAL; 285 return nullptr; 286 } 287 // check whitelist 288 if (!CheckWhiteList(command[0])) { 289 PROFILER_LOG_ERROR(LOG_CORE, "%s: command not in whitelist!", __func__); 290 return nullptr; 291 } 292 // check cmd arg valid 293 for (auto& item : command) { 294 if (!CheckCmdLineArgValid(item)) { 295 PROFILER_LOG_ERROR(LOG_CORE, "%s: command arg invalid : %s", __func__, item.c_str()); 296 return nullptr; 297 } 298 } 299 CHECK_TRUE(pipe(fds) == 0, nullptr, "Pipe open failed!"); 300 pid_t pid = fork(); 301 if (pid == -1) { 302 perror("fork"); 303 exit(1); 304 } 305 306 if (pid == 0) { 307 // execve : the last argv must be nullptr. 308 std::vector<char*> argv(command.size() + 1, nullptr); 309 for (size_t i = 0, cmdSize = command.size(); i < cmdSize; i++) { 310 argv[i] = const_cast<char*>(command[i].data()); 311 } 312 313 if (strncmp(type, "r", strlen(type)) == 0) { 314 CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "CustomFdClose failed!"); 315 dup2(fds[WRITE], STDOUT_FILENO); // Redirect stdout to pipe 316 CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "CustomFdClose failed!"); 317 } else { 318 CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "CustomFdClose failed!"); 319 dup2(fds[READ], STDIN_FILENO); // Redirect stdin to pipe 320 CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "CustomFdClose failed!"); 321 } 322 323 setpgid(pid, pid); 324 // exe path = argv[0]; exe name = argv[1] 325 if (execv(argv[0], &argv[1]) == -1) { 326 PROFILER_LOG_ERROR(LOG_CORE, "execv failed {%s:%s}", __func__, strerror(errno)); 327 exit(EXIT_FAILURE); 328 } 329 } 330 331 if (!needUnblock) { 332 if (strncmp(type, "r", strlen(type)) == 0) { 333 // Close the WRITE end of the pipe since parent's fd is read-only 334 CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "%s %d CustomFdClose failed! errno(%s)\n", 335 __func__, __LINE__, strerror(errno)); 336 } else { 337 // Close the READ end of the pipe since parent's fd is write-only 338 CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "%s %d CustomFdClose failed! errno(%s)\n", 339 __func__, __LINE__, strerror(errno)); 340 } 341 } 342 343 // Make sure the parent pipe reads and writes exist;CustomPUnblock will use. 344 childPid = pid; 345 if (strncmp(type, "r", strlen(type)) == 0) { 346 PROFILER_LOG_DEBUG(LOG_CORE, "END %s fds[READ]: success!", __func__); 347 return fdopen(fds[READ], "r"); 348 } 349 350 PROFILER_LOG_DEBUG(LOG_CORE, "END %s fds[WRITE]: success!", __func__); 351 return fdopen(fds[WRITE], "w"); 352} 353 354bool IsNumeric(const std::string& str) 355{ 356 std::istringstream iss(str); 357 int number; 358 char trailingCharacter; 359 if (!(iss >> number)) { 360 return false; 361 } 362 if (iss >> trailingCharacter) { 363 return false; 364 } 365 return true; 366} 367 368int CustomPclose(FILE* fp, int fds[], volatile pid_t& childPid, bool needUnblock) 369{ 370 PROFILER_LOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__); 371 CHECK_NOTNULL(fp, -1, "NOTE %s: fp is null", __func__); 372 373 int stat = 0; 374 375 if (needUnblock) { 376 PROFILER_LOG_DEBUG(LOG_CORE, "NOTE Kill Endless Loop Child %d.", childPid); 377 kill(childPid, SIGKILL); 378 } 379 380 while (waitpid(childPid, &stat, 0) == -1) { 381 PROFILER_LOG_ERROR(LOG_CORE, "%s: %s.", __func__, strerror(errno)); 382 if (errno == EINTR) { 383 continue; 384 } 385 break; 386 } 387 388 if (needUnblock) { 389 if (fileno(fp) == fds[READ]) { 390 fds[READ] = -1; 391 if (CustomFdClose(fds[WRITE]) != 0) { 392 PROFILER_LOG_ERROR(LOG_CORE, "CustomFdClose failed!"); 393 CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!"); 394 return -1; 395 } 396 } else if (fileno(fp) == fds[WRITE]) { 397 fds[WRITE] = -1; 398 if (CustomFdClose(fds[READ]) != 0) { 399 PROFILER_LOG_ERROR(LOG_CORE, "CustomFdClose failed!"); 400 CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!"); 401 return -1; 402 } 403 } else { 404 PROFILER_LOG_INFO(LOG_CORE, "%s: Can't find fp in fds[READ/WRITE].", __func__); 405 } 406 } 407 408 CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!"); 409 410 PROFILER_LOG_DEBUG(LOG_CORE, "END %s: success!", __func__); 411 return stat; 412} 413 414// IF pipe fds is block, before release other threads, you need call CustomPUnblock 415int CustomPUnblock(int fds[]) 416{ 417 PROFILER_LOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__); 418 419 CHECK_TRUE(fds[READ] != -1 && fds[WRITE] != -1, -1, "END fds[READ/WRITE]=-1"); 420 421 int stat = fcntl(fds[READ], F_GETFL); 422 CHECK_TRUE(stat != -1, -1, "END fcntl(F_GETFL) failed!"); 423 424 if (!(stat & O_NONBLOCK)) { 425 PROFILER_LOG_DEBUG(LOG_CORE, "NOTE %s: ready!Unblock r_fd and close all", __func__); 426 const char* eof = "\n\0"; 427 write(fds[WRITE], eof, strlen(eof) + 1); 428 fcntl(fds[READ], F_SETFL, O_NONBLOCK); 429 } 430 PROFILER_LOG_DEBUG(LOG_CORE, "END %s: success!", __func__); 431 return 0; 432} 433 434int GetServicePort() 435{ 436 const std::string portRangePath = "/proc/sys/net/ipv4/ip_local_port_range"; 437 std::ifstream file(portRangePath.c_str()); 438 CHECK_TRUE(file.is_open(), -1, "Open file failed! filePath:%s", portRangePath.c_str()); 439 440 std::string rangeStr; 441 copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(rangeStr)); 442 443 int minPort; 444 int maxPort; 445 std::istringstream istr(rangeStr); 446 istr >> minPort >> maxPort; 447 const int offset = 3168; // To be compatible with previously used port 50051; 448 int port = (minPort + maxPort) / 2 + offset; 449 PROFILER_LOG_DEBUG(LOG_CORE, "Service port is: %d", port); 450 return port; 451} 452 453void SplitString(const std::string& str, const std::string &sep, std::vector<std::string>& ret) 454{ 455 if (str.empty()) { 456 PROFILER_LOG_ERROR(LOG_CORE, "The string splited is empty!"); 457 return; 458 } 459 std::string::size_type beginPos = str.find_first_not_of(sep); 460 std::string::size_type findPos = 0; 461 while (beginPos != std::string::npos) { 462 findPos = str.find(sep, beginPos); 463 std::string tmp; 464 if (findPos != std::string::npos) { 465 tmp = str.substr(beginPos, findPos - beginPos); 466 beginPos = findPos + sep.length(); 467 } else { 468 tmp = str.substr(beginPos); 469 beginPos = findPos; 470 } 471 if (!tmp.empty()) { 472 ret.push_back(tmp); 473 tmp.clear(); 474 } 475 } 476} 477 478bool CheckApplicationPermission(int pid, const std::string& processName) 479{ 480 std::string bundleName; 481 if (pid > 0) { 482 std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline"; 483 if (!LoadStringFromFile(filePath, bundleName)) { 484 PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!"); 485 return false; 486 } 487 bundleName.resize(strlen(bundleName.c_str())); 488 } else { 489 bundleName = processName; 490 } 491 auto pos = bundleName.find(":"); 492 if (pos != std::string::npos) { 493 bundleName = bundleName.substr(0, pos); 494 } 495 CHECK_TRUE(!bundleName.empty(), false, "Pid or process name is illegal!"); 496 497 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 498 CHECK_NOTNULL(sam, false, "GetSystemAbilityManager failed!"); 499 sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); 500 CHECK_NOTNULL(remoteObject, false, "Get BundleMgr SA failed!"); 501 sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject); 502 AppExecFwk::ApplicationInfo appInfo; 503 bool ret = proxy->GetApplicationInfo(bundleName, AppExecFwk::GET_APPLICATION_INFO_WITH_DISABLE, 504 AppExecFwk::Constants::ANY_USERID, appInfo); 505 if (!ret) { 506 PROFILER_LOG_ERROR(LOG_CORE, "GetApplicationInfo failed!"); 507 return false; 508 } 509 return appInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG; 510} 511bool CheckApplicationEncryped(int pid, const std::string& processName) 512{ 513 std::string bundleName; 514 if (pid > 0) { 515 std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline"; 516 if (!LoadStringFromFile(filePath, bundleName)) { 517 PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!"); 518 return false; 519 } 520 bundleName.resize(strlen(bundleName.c_str())); 521 } else { 522 bundleName = processName; 523 } 524 auto pos = bundleName.find(":"); 525 if (pos != std::string::npos) { 526 bundleName = bundleName.substr(0, pos); 527 } 528 CHECK_TRUE(!bundleName.empty(), false, "Pid or process name is illegal!"); 529 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 530 CHECK_NOTNULL(sam, false, "GetSystemAbilityManager failed!"); 531 sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); 532 CHECK_NOTNULL(remoteObject, false, "Get BundleMgr SA failed!"); 533 sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject); 534 AppExecFwk::ApplicationInfo appInfo; 535 bool ret = proxy->GetApplicationInfo(bundleName, AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO, 536 AppExecFwk::Constants::ANY_USERID, appInfo); 537 CHECK_TRUE(ret, false, "%s:%s GetApplicationInfo failed!", __func__, bundleName.c_str()); 538 bool isEncrypted = (appInfo.applicationReservedFlag & 539 static_cast<uint32_t>(AppExecFwk::ApplicationReservedFlag::ENCRYPTED_APPLICATION)) != 0; 540 PROFILER_LOG_INFO(LOG_CORE, "%s: check application encryped.%d : %s", __func__, isEncrypted, bundleName.c_str()); 541 return isEncrypted; 542} 543 544bool VerifyPath(const std::string& filePath, const std::vector<std::string>& validPaths) 545{ 546 if (validPaths.size() == 0) { 547 return true; 548 } 549 550 for (const std::string& path : validPaths) { 551 if (filePath.rfind(path, 0) == 0) { 552 return true; 553 } 554 } 555 return false; 556} 557 558const char* RealPath(std::string &filePath) 559{ 560 if (filePath.size() > 0 && (filePath.back() == '/' || filePath.back() == '.')) { 561 return nullptr; 562 } 563 if (filePath.find('.') == std::string::npos) { 564 return filePath.c_str(); 565 } 566 std::vector<std::string> paths; 567 SplitString(filePath, "/", paths); 568 std::vector<std::string> validPaths; 569 for (std::string& pathName: paths) { 570 if (pathName == "..") { 571 if (validPaths.size() == 0) { 572 return nullptr; 573 } else { 574 validPaths.pop_back(); 575 } 576 } else { 577 validPaths.emplace_back(pathName); 578 } 579 } 580 filePath = "/"; 581 for (const std::string &pathName : validPaths) { 582 filePath += pathName; 583 filePath += "/"; 584 } 585 filePath.pop_back(); 586 return filePath.c_str(); 587} 588 589bool ReadFile(const std::string &filePath, const std::vector<std::string>& validPaths, std::string& fileContent) 590{ 591 std::string pathName = filePath; 592 const char* realFilePath = RealPath(pathName); 593 CHECK_NOTNULL(realFilePath, false, "Fail to realPath: %s", filePath.c_str()); 594 595 std::string realFilePathStr(realFilePath); 596 CHECK_TRUE(VerifyPath(realFilePathStr, validPaths), false, "Fail to VerifyPath: %s", realFilePathStr.c_str()); 597 598 std::ifstream fileStream(realFilePathStr, std::ios::in); 599 CHECK_TRUE(fileStream.is_open(), false, "Fail to open file %s", realFilePathStr.c_str()); 600 601 std::istreambuf_iterator<char> firstIt = { fileStream }; 602 std::string content(firstIt, {}); 603 fileContent = content; 604 return true; 605} 606 607bool IsUserMode() 608{ 609 std::string debugMode = "0"; 610 debugMode = OHOS::system::GetParameter("const.debuggable", debugMode); 611 if (debugMode != "0") { 612 PROFILER_LOG_INFO(LOG_CORE, "It is not user mode!"); 613 } 614 return debugMode == "0"; 615} 616 617std::string GetErrorMsg() 618{ 619 const int bufSize = 256; 620 char buffer[bufSize] = { 0 }; 621 strerror_r(errno, buffer, bufSize); 622 std::string errorMsg(buffer); 623 return errorMsg; 624} 625 626std::string GetTimeStr() 627{ 628 time_t now = time(nullptr); 629 struct tm tmTime; 630 localtime_r(&now, &tmTime); 631 632 char buffer[32] = {0}; 633 // 1900: count of years 634 (void)sprintf_s(buffer, sizeof(buffer), "%04d%02d%02d_%02d%02d%02d", tmTime.tm_year + 1900, tmTime.tm_mon + 1, 635 tmTime.tm_mday, tmTime.tm_hour, tmTime.tm_min, tmTime.tm_sec); 636 std::string timeStr(buffer); 637 return timeStr; 638} 639 640// get clockid by str, return CLOCK_REALTIME as default 641clockid_t GetClockId(const std::string& clockIdStr) 642{ 643 clockid_t clockId = CLOCK_REALTIME; 644 auto iter = clockIdMap.find(clockIdStr); 645 if (iter != clockIdMap.end()) { 646 clockId = iter->second; 647 } 648 return clockId; 649} 650 651std::string GetClockStr(const int32_t clockId) 652{ 653 std::string ret = "realtime"; 654 for (const auto& [str, id] : clockIdMap) { 655 if (id == clockId) { 656 ret = str; 657 break; 658 } 659 } 660 return ret; 661} 662 663void AdaptSandboxPath(std::string& filePath, int pid) 664{ 665 if (filePath.find("/data/storage") == 0 && access(filePath.c_str(), F_OK) != 0) { 666 filePath = "/proc/" + std::to_string(pid) + "/root" + filePath; 667 } 668} 669 670bool GetCurrentUserId(int32_t& userId) 671{ 672 std::vector<int32_t> activeIds; 673 int32_t ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(activeIds); 674 if (ret != 0) { 675 PROFILER_LOG_ERROR(LOG_CORE, "QueryActiveOsAccountIds failed ret:%d", ret); 676 return false; 677 } 678 679 if (activeIds.empty()) { 680 PROFILER_LOG_ERROR(LOG_CORE, "QueryActiveOsAccountIds activeIds empty"); 681 return false; 682 } 683 userId = activeIds[0]; 684 PROFILER_LOG_INFO(LOG_CORE, "QueryActiveOsAccountIds userId[0]:%d", userId); 685 return true; 686} 687 688int32_t GetPackageUid(const std::string& name) 689{ 690 int32_t userId = 0; 691 if (!GetCurrentUserId(userId)) { 692 PROFILER_LOG_ERROR(LOG_CORE, "Failed to get current user id"); 693 return EC_INVALID_VALUE; 694 } 695 auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 696 if (manager == nullptr) { 697 PROFILER_LOG_ERROR(LOG_CORE, "systemAbilityManager is nullptr"); 698 return EC_INVALID_VALUE; 699 } 700 sptr<IRemoteObject> remoteObject = manager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); 701 if (remoteObject == nullptr) { 702 PROFILER_LOG_ERROR(LOG_CORE, "failed to get service id"); 703 return EC_INVALID_VALUE; 704 } 705 sptr<AppExecFwk::IBundleMgr> mgr = iface_cast<AppExecFwk::IBundleMgr>(remoteObject); 706 if (mgr == nullptr) { 707 PROFILER_LOG_ERROR(LOG_CORE, "mgr is nullptr"); 708 return EC_INVALID_VALUE; 709 } 710 int32_t uid = mgr->GetUidByBundleName(name, userId); 711 PROFILER_LOG_INFO(LOG_CORE, "pkgname is: %s, uid is : %d", name.c_str(), uid); 712 return uid; 713} 714 715bool IsBetaVersion() 716{ 717 int ret = static_cast<int>(FindParameter(KEY_HIVIEW_USER_TYPE.c_str())); 718 if (ret == -1) { 719 PROFILER_LOG_INFO(LOG_CORE, "user type is not exist"); 720 return true; 721 } 722 std::string userType = OHOS::system::GetParameter(KEY_HIVIEW_USER_TYPE, ""); 723 PROFILER_LOG_INFO(LOG_CORE, "user type is:%s", userType.c_str()); 724 return userType == "beta"; 725} 726 727std::pair<bool, std::string> CheckNotExistsFilePath(const std::string& filePath) 728{ 729 size_t pos = filePath.rfind('/'); 730 std::string pathDir = ""; 731 if (pos != std::string::npos) { 732 pathDir = filePath.substr(0, pos); 733 } else { 734 pathDir = "."; 735 } 736 std::unique_ptr<char[]> pathDirRealPath = std::make_unique<char[]>(PATH_MAX); 737 if ((pathDir.length() >= PATH_MAX - 1) || (realpath(pathDir.c_str(), pathDirRealPath.get()) == nullptr)) { 738 PROFILER_LOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, pathDir.c_str(), errno); 739 return {false, ""}; 740 } 741 if (access(pathDir.c_str(), F_OK) != 0) { 742 PROFILER_LOG_ERROR(LOG_CORE, "%s:Fail to access path: %s", __func__, pathDir.c_str()); 743 return {false, ""}; 744 } 745 return {true, std::string(pathDirRealPath.get()) + "/" + filePath.substr(pos + 1)}; 746} 747 748bool CheckWhiteList(const std::string& cmdPath) 749{ 750 if (cmdPath.empty()) { 751 PROFILER_LOG_ERROR(LOG_CORE, "cmd is empty {%s}", __func__); 752 return false; 753 } 754 755 if (CMD_WHITE_LIST.find(cmdPath) == CMD_WHITE_LIST.end() || 756 cmdPath.find_first_of("|;&${}<>'\\!\n~?*%[]^") != std::string::npos) { 757 PROFILER_LOG_ERROR(LOG_CORE, "cmd %s:is illegal {%s}", cmdPath.c_str(), __func__); 758 return false; 759 } 760 return true; 761} 762 763bool CheckCmdLineArgValid(const std::string& cmdLine) 764{ 765 if (cmdLine.empty()) { 766 PROFILER_LOG_ERROR(LOG_CORE, "cmdLine is empty {%s}", __func__); 767 return false; 768 } 769 770 if (cmdLine.find_first_of("|;&${}<>'\\!\n~?*%[]^") != std::string::npos) { 771 PROFILER_LOG_ERROR(LOG_CORE, "cmdLine %s is illegal {%s}", cmdLine.c_str(), __func__); 772 return false; 773 } 774 return true; 775} 776} // namespace COMMON 777