LCOV - code coverage report
Current view: top level - pub_facility/util_func - tsd_util_func.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.1 % 241 210
Test Date: 2026-07-28 10:52:48 Functions: 100.0 % 27 27

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "tsd_util_func.h"
      12              : #include <iostream>
      13              : #include <fstream>
      14              : #include <algorithm>
      15              : #include <cctype>
      16              : #include <csignal>
      17              : #include <cstring>
      18              : #include <dirent.h>
      19              : #include <dlfcn.h>
      20              : #include <semaphore.h>
      21              : #include <thread>
      22              : #include <cerrno>
      23              : #include <sys/wait.h>
      24              : #include <regex.h>
      25              : #include <climits>
      26              : #include <cstdlib>
      27              : #include <sstream>
      28              : #include <iomanip>
      29              : #include "basic_define.h"
      30              : #include "weak_ascend_hal.h"
      31              : #include "tsd_sha256.h"
      32              : #include "tsd_log.h"
      33              : 
      34              : namespace {
      35              : constexpr int32_t SYSTE_EXECUTE_CMD_ERROR = 127; // 与system实现保持一致
      36              : // min number of vDeviceId
      37              : constexpr const uint32_t VDEVICE_MIN_CPU_NUM = 32U;
      38              : // max number of vDeviceId
      39              : constexpr const uint32_t VDEVICE_MAX_CPU_NUM = 64U;
      40              : } // namespace
      41              : 
      42              : namespace tsd {
      43          136 : void Trim(std::string& str)
      44              : {
      45          136 :     if (str.empty()) {
      46            2 :         return;
      47              :     }
      48          134 :     (void)str.erase(static_cast<size_t>(0), str.find_first_not_of(" "));
      49          134 :     (void)str.erase(str.find_last_not_of(" ") + static_cast<size_t>(1));
      50              : }
      51              : 
      52           26 : void TrimWhitespace(std::string& str)
      53              : {
      54           56 :     auto isSpace = [](unsigned char c) { return std::isspace(c) != 0; };
      55           29 :     while (!str.empty() && isSpace(static_cast<unsigned char>(str.back()))) {
      56            3 :         str.pop_back();
      57              :     }
      58           26 :     size_t pos = 0U;
      59           29 :     while (pos < str.size() && isSpace(static_cast<unsigned char>(str[pos]))) {
      60            3 :         ++pos;
      61              :     }
      62           26 :     if (pos > 0U) {
      63            2 :         (void)str.erase(0U, pos);
      64              :     }
      65           26 : }
      66              : 
      67           32 : std::vector<std::string> SplitByChar(const std::string& s, char sep)
      68              : {
      69           32 :     std::vector<std::string> tokens;
      70           32 :     std::string cur;
      71          181 :     for (char c : s) {
      72          149 :         if (c == sep) {
      73           57 :             tokens.emplace_back(std::move(cur));
      74           57 :             cur.clear();
      75              :         } else {
      76           92 :             cur.push_back(c);
      77              :         }
      78              :     }
      79           32 :     tokens.emplace_back(std::move(cur));
      80           32 :     return tokens;
      81           32 : }
      82              : 
      83           40 : int32_t CompareSegmentNumeric(const std::string& a, const std::string& b)
      84              : {
      85           80 :     auto allDigit = [](const std::string& s) {
      86          160 :         return !s.empty() &&
      87          241 :                std::all_of(s.begin(), s.end(), [](char c) { return std::isdigit(static_cast<unsigned char>(c)) != 0; });
      88              :     };
      89           40 :     const bool aDigit = allDigit(a);
      90           40 :     const bool bDigit = allDigit(b);
      91           40 :     if (aDigit && bDigit) {
      92           37 :         std::string aa = a;
      93           37 :         std::string bb = b;
      94           37 :         size_t pa = aa.find_first_not_of('0');
      95           37 :         size_t pb = bb.find_first_not_of('0');
      96           44 :         aa = (pa == std::string::npos) ? "0" : aa.substr(pa);
      97           44 :         bb = (pb == std::string::npos) ? "0" : bb.substr(pb);
      98           37 :         if (aa.size() != bb.size()) {
      99            1 :             return (aa.size() < bb.size()) ? -1 : 1;
     100              :         }
     101           36 :         if (aa == bb) {
     102           29 :             return 0;
     103              :         }
     104            7 :         return (aa < bb) ? -1 : 1;
     105           37 :     }
     106            3 :     if (a == b) {
     107            1 :         return 0;
     108              :     }
     109            2 :     return (a < b) ? -1 : 1;
     110              : }
     111              : 
     112           14 : uint64_t CalFileSize(const std::string& filePath)
     113              : {
     114           14 :     struct stat st = {};
     115           14 :     const auto ret = lstat(filePath.c_str(), &st);
     116           14 :     if (ret != 0) {
     117           13 :         TSD_RUN_WARN(
     118              :             "Getting the file stat was not successful, ret=%d, path=%s, reason=%s", ret, filePath.c_str(),
     119              :             SafeStrerror().c_str());
     120           13 :         return 0UL;
     121              :     }
     122              : 
     123            1 :     return st.st_size;
     124              : }
     125              : 
     126          833 : bool ValidateStr(const std::string& str, const std::string& mode)
     127              : {
     128              :     regex_t reg;
     129          833 :     int32_t ret = regcomp(&reg, mode.c_str(), REG_EXTENDED | REG_NOSUB);
     130          833 :     if (ret != 0) {
     131            0 :         return false;
     132              :     }
     133          833 :     ret = regexec(&reg, str.c_str(), static_cast<size_t>(0), nullptr, 0);
     134          833 :     if (ret != 0) {
     135          545 :         regfree(&reg);
     136          545 :         return false;
     137              :     }
     138              : 
     139          288 :     regfree(&reg);
     140          288 :     return true;
     141              : }
     142              : 
     143           43 : void GetScheduleEnv(const char_t* const envName, std::string& envValue)
     144              : {
     145           43 :     const size_t envValueMaxLen = 1024UL * 1024UL;
     146           43 :     if (envName == nullptr) {
     147            1 :         return;
     148              :     }
     149              :     try {
     150           42 :         const char_t* const envTemp = std::getenv(envName);
     151           42 :         if ((envTemp == nullptr) || (strnlen(envTemp, envValueMaxLen) >= envValueMaxLen)) {
     152            3 :             TSD_WARN("Get env[%s] failed", envName);
     153            3 :             return;
     154              :         }
     155           39 :         envValue = envTemp;
     156            0 :     } catch (std::exception& e) {
     157            0 :         TSD_ERROR("get env failed:[%s]", e.what());
     158            0 :     }
     159              : }
     160              : 
     161            4 : bool GetFlagFromEnv(const char_t* const envStr, const char_t* const envValue)
     162              : {
     163            4 :     std::string isFlag;
     164            4 :     GetScheduleEnv(envStr, isFlag);
     165            4 :     if (!isFlag.empty()) {
     166            2 :         if (isFlag == envValue) {
     167            1 :             return true;
     168              :         }
     169              :     }
     170            3 :     return false;
     171            4 : }
     172              : 
     173          172 : bool IsFpgaEnv()
     174              : {
     175          172 :     static const bool isFpga = GetFlagFromEnv("DATAMASTER_RUN_MODE", "1");
     176          172 :     return isFpga;
     177              : }
     178              : 
     179          112 : bool CheckRealPath(const std::string& inputPath)
     180              : {
     181          112 :     if (inputPath.empty()) {
     182            0 :         TSD_RUN_INFO("Input path is empty");
     183            0 :         return false;
     184              :     }
     185          112 :     if (inputPath.length() >= static_cast<size_t>(PATH_MAX)) {
     186            0 :         TSD_RUN_INFO("Input path must less than [%d]", PATH_MAX);
     187            0 :         return false;
     188              :     }
     189          112 :     std::unique_ptr<char_t[]> path(new (std::nothrow) char_t[PATH_MAX]);
     190          112 :     if (path == nullptr) {
     191            0 :         TSD_RUN_WARN("Alloc memory for path failed.");
     192            0 :         return false;
     193              :     }
     194              : 
     195          112 :     const auto eRet = memset_s(path.get(), PATH_MAX, 0, PATH_MAX);
     196          112 :     if (eRet != EOK) {
     197            0 :         TSD_RUN_WARN("Mem set error, ret= [%d]", eRet);
     198            0 :         return false;
     199              :     }
     200              : 
     201          112 :     if (realpath(inputPath.data(), path.get()) == nullptr) {
     202          103 :         TSD_RUN_WARN("Format to realpath failed, inputPath is [%s]", inputPath.c_str());
     203          103 :         return false;
     204              :     }
     205            9 :     std::string normalizedPath(path.get());
     206            9 :     if (normalizedPath[normalizedPath.size() - static_cast<size_t>(1)] != '/') {
     207            9 :         (void)normalizedPath.append("/");
     208              :     }
     209            9 :     if (strncmp(normalizedPath.c_str(), inputPath.c_str(), inputPath.length()) != 0) {
     210            0 :         TSD_RUN_INFO("Invalid path [%s], should be [%s]", inputPath.c_str(), normalizedPath.c_str());
     211            0 :         return false;
     212              :     }
     213            9 :     return true;
     214          112 : }
     215              : 
     216           14 : bool CheckValidatePath(const std::string& path)
     217              : {
     218           14 :     const std::string pathPattern = "^[0-9a-zA-Z\\/\\_\\.\\-]+$";
     219           28 :     return ValidateStr(path, pathPattern);
     220           14 : }
     221              : 
     222            8 : int32_t TsdExecuteCmd(const std::string& cmd)
     223              : {
     224            8 :     if (cmd.empty()) {
     225            0 :         return -1;
     226              :     }
     227              : 
     228            8 :     int32_t status = 0;
     229            8 :     const int32_t pid = vfork();
     230           16 :     if (pid < 0) {
     231            0 :         status = -1;
     232           16 :     } else if (pid == 0) {
     233            8 :         (void)execl("/bin/sh", "sh", "-c", cmd.c_str(), nullptr);
     234            0 :         _exit(SYSTE_EXECUTE_CMD_ERROR);
     235              :     } else {
     236            8 :         while (waitpid(pid, &status, 0) < 0) {
     237            0 :             if (errno != EINTR) {
     238            0 :                 status = -1;
     239            0 :                 break;
     240              :             }
     241              :         }
     242              :     }
     243              : 
     244            8 :     return status;
     245              : }
     246              : 
     247            8 : int32_t PackSystem(const char_t* const cmdLine)
     248              : {
     249            8 :     const sighandler_t oldHandler = signal(SIGCHLD, nullptr);
     250              :     // system()函数失败是由于“ No child processes”
     251              :     // 如果SIGCHLD信号行为被设置为SIG_IGN时,waitpid()函数有可能因为找不到子进程而报ECHILD错误
     252              :     // 是因为system()函数依赖了系统的一个特性,那就是内核初始化进程时对SIGCHLD信号的处理方式为SIG_DFL
     253            8 :     const int32_t ret = TsdExecuteCmd(cmdLine);
     254            8 :     TSD_INFO(
     255              :         "[TSDaemon] PackSystem cmd: [%s], result: [%d], errno[%d], reason[%s].", cmdLine, ret, errno,
     256              :         SafeStrerror().c_str());
     257            8 :     (void)signal(SIGCHLD, oldHandler);
     258            8 :     return ret;
     259              : }
     260              : 
     261           52 : static bool IsTinyRuntime()
     262              : {
     263              : #ifdef TINY_RUNTIME
     264              :     return true;
     265              : #else
     266           52 :     return false;
     267              : #endif
     268              : }
     269              : 
     270              : /**
     271              :  * int strerror_r(int errnum, char buf[.buflen], size_t buflen); POSIX
     272              :  * char *strerror_r(int errnum, char buf[.buflen], size_t buflen); GNU
     273              :  */
     274           52 : std::string SafeStrerror()
     275              : {
     276           52 :     const uint32_t errnoLen = 256U;
     277           52 :     char_t errBuf[errnoLen] = {};
     278           52 :     auto errorMsg = strerror_r(errno, &errBuf[0], errnoLen);
     279           52 :     if (IsTinyRuntime()) {
     280            0 :         if (errorMsg == 0) {
     281            0 :             errBuf[errnoLen - 1U] = '\0';
     282            0 :             return std::string(errBuf);
     283              :         }
     284              :     } else {
     285           52 :         const char_t* errorMsgStr = reinterpret_cast<char_t*>(errorMsg);
     286           52 :         if (errorMsgStr != nullptr) {
     287          104 :             return std::string(errorMsgStr);
     288              :         }
     289              :     }
     290            0 :     return "";
     291              : }
     292              : 
     293           24 : uint32_t CalcUniqueVfId(const uint32_t deviceId, const uint32_t vfId)
     294              : {
     295           24 :     if (IsVfModeCheckedByDeviceId(deviceId)) {
     296            1 :         return deviceId;
     297              :     }
     298              : 
     299           23 :     if ((deviceId == 0U) || (vfId == 0U)) {
     300           23 :         return vfId;
     301              :     }
     302              : 
     303              :     static uint32_t maxNumSpDev = 0U;
     304            0 :     if ((&halGetDeviceVfMax != nullptr) && (maxNumSpDev == 0U)) {
     305            0 :         const auto retRes = halGetDeviceVfMax(deviceId, &maxNumSpDev);
     306            0 :         if ((retRes != DRV_ERROR_NONE) || (maxNumSpDev > DEVICE_MAX_SPLIT_NUM)) {
     307            0 :             TSD_ERROR("Failed to get device cat vf number, result[%d], max num[%u].", retRes, maxNumSpDev);
     308            0 :             return UINT32_MAX;
     309              :         }
     310              :     }
     311            0 :     return (maxNumSpDev * deviceId) + vfId;
     312              : }
     313              : 
     314           35 : bool TransStrToInt(const std::string& para, int32_t& value)
     315              : {
     316              :     try {
     317           35 :         value = std::stoi(para);
     318           14 :     } catch (...) {
     319           14 :         return false;
     320           14 :     }
     321              : 
     322           21 :     return true;
     323              : }
     324              : 
     325           14 : void RemoveOneFile(const std::string& filePath)
     326              : {
     327           14 :     if (filePath.empty()) {
     328            4 :         return;
     329              :     }
     330              : 
     331           10 :     if (access(filePath.c_str(), F_OK) != 0) {
     332            8 :         TSD_INFO("The file does not exist, no need to remove, path=%s", filePath.c_str());
     333            8 :         return;
     334              :     }
     335              : 
     336            2 :     const int32_t ret = remove(filePath.c_str());
     337            2 :     if (ret != 0) {
     338            1 :         TSD_RUN_WARN(
     339              :             "Removing the file was not successful, ret=%d, path=%s, reason=%s", ret, filePath.c_str(),
     340              :             SafeStrerror().c_str());
     341            1 :         return;
     342              :     }
     343              : 
     344            1 :     TSD_INFO("Remove file success, path=%s", filePath.c_str());
     345              : }
     346              : 
     347            3 : bool IsDirEmpty(const std::string& dirPath)
     348              : {
     349            3 :     DIR* dir = opendir(dirPath.c_str());
     350            3 :     if (!dir) {
     351            1 :         return true;
     352              :     }
     353              : 
     354              :     struct dirent* entry;
     355            2 :     int count = 0;
     356              : 
     357            6 :     while ((entry = readdir(dir)) != nullptr) {
     358            5 :         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
     359            4 :             continue;
     360              :         }
     361              : 
     362            1 :         count++;
     363            1 :         if (count > 0) {
     364            1 :             (void)closedir(dir);
     365            1 :             return false;
     366              :         }
     367              :     }
     368              : 
     369            1 :     (void)closedir(dir);
     370            1 :     return true;
     371              : }
     372              : 
     373            9 : std::string CalFileSha256HashValue(const std::string& filePath)
     374              : {
     375            9 :     std::ifstream curFile(filePath, std::ios::binary);
     376            9 :     if (!curFile) {
     377            2 :         TSD_RUN_WARN("Opening file:%s was not successful, reason:%s", filePath.c_str(), SafeStrerror().c_str());
     378            4 :         return "";
     379              :     }
     380              : 
     381            7 :     std::stringstream fileBuffer;
     382            7 :     fileBuffer << curFile.rdbuf();
     383            7 :     std::string fileBinaryValue = fileBuffer.str();
     384              :     std::string hashHex =
     385            7 :         sha256::ComputeHexString(PtrToPtr<const char, const uint8_t>(fileBinaryValue.c_str()), fileBinaryValue.size());
     386            7 :     curFile.close();
     387            7 :     return hashHex;
     388            9 : }
     389              : 
     390           23 : bool IsCurrentVfMode(const uint32_t deviceId, const uint32_t vfId)
     391              : {
     392           23 :     if ((IsVfModeCheckedByDeviceId(deviceId)) || (vfId > 0)) {
     393            2 :         return true;
     394              :     } else {
     395           21 :         return false;
     396              :     }
     397              : }
     398              : 
     399            3 : std::string ExtractSubString(const std::string& input, const std::string& begin, const std::string& end)
     400              : {
     401            3 :     size_t pos = input.find(begin);
     402            3 :     if (pos == std::string::npos) {
     403            2 :         return "";
     404              :     }
     405            2 :     size_t left = pos + begin.length();
     406            2 :     size_t right = input.find(end, left);
     407            2 :     if (right == std::string::npos) {
     408            0 :         return "";
     409              :     }
     410            2 :     return input.substr(left, right - left);
     411              : }
     412              : 
     413           67 : bool IsVfModeCheckedByDeviceId(const uint32_t deviceId)
     414              : {
     415           67 :     if ((deviceId >= VDEVICE_MIN_CPU_NUM) && (deviceId < VDEVICE_MAX_CPU_NUM)) {
     416            4 :         return true;
     417              :     } else {
     418           63 :         return false;
     419              :     }
     420              : }
     421              : 
     422          571 : std::string GetHostSoPath()
     423              : {
     424          571 :     Dl_info info = {};
     425          571 :     if (dladdr(reinterpret_cast<void*>(drvHdcSendFile), &info) == 0) {
     426            1 :         TSD_INFO("Getting the host so path was not successful, reason[%s], errno[%d]", SafeStrerror().c_str(), errno);
     427            2 :         return "";
     428              :     }
     429          570 :     TSD_INFO("dli_fname[%s]", info.dli_fname);
     430          570 :     if (info.dli_fname == nullptr) {
     431            2 :         return "";
     432              :     }
     433          569 :     std::string path(info.dli_fname);
     434          569 :     const size_t pos = path.find_last_of('/');
     435          569 :     std::string hostSoPath;
     436          569 :     if (pos != std::string::npos) {
     437          568 :         hostSoPath = path.substr(0, pos + static_cast<size_t>(1));
     438              :     } else {
     439            1 :         hostSoPath = "./";
     440              :     }
     441          569 :     TSD_INFO("host so path[%s]", hostSoPath.c_str());
     442          569 :     return hostSoPath;
     443          569 : }
     444              : } // namespace tsd
        

Generated by: LCOV version 2.0-1