* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "utils.h"
#include <errno.h>
#include "securec.h"
#include "inttypes.h"
#include "logger/logger.h"
#include "errno/error_code.h"
#include "osal/osal_mem.h"
#include "time.h"
void *MsprofRealloc(void *ptr, size_t oldSize, size_t newSize)
{
if (oldSize == 0 || newSize == 0) {
MSPROF_LOGE("Invalid ralloc oldSize %zu or newSize %zu", oldSize, newSize);
return NULL;
}
void *newPtr = OsalMalloc(newSize);
if (newPtr == NULL) {
MSPROF_LOGE("ralloc failed, newSize=%zu.", newSize);
return NULL;
}
int32_t ret = memcpy_s(newPtr, newSize, ptr, oldSize);
if (ret != EOK) {
OsalFree(newPtr);
MSPROF_LOGE("memcpy_s from realloc failed, newSize=%zu.", newSize);
return NULL;
}
OsalFree(ptr);
return newPtr;
}
#ifndef LITE_OS
bool GetCwdString(const CHAR* path, CHAR* resultDir, size_t len)
{
static char val[CWD_VAL_MAX_LEN];
(void)memset_s(val, CWD_VAL_MAX_LEN, 0, CWD_VAL_MAX_LEN);
int32_t ret = OsalGetCwd(val, CWD_VAL_MAX_LEN - 1);
if (ret == OSAL_EN_OK) {
ret = sprintf_s(resultDir, len, "%s/%s", val, path);
if (ret < 0) {
MSPROF_LOGE("sprintf fail for dir %s.", path);
return false;
}
}
return true;
}
bool RelativePathToAbsolutePath(const CHAR* path, CHAR* resultDir, size_t len)
{
bool boolStatus = true;
if (path == NULL || resultDir == NULL || strlen(path) == 0) {
MSPROF_LOGE("Path or result path %s is empty", path);
return false;
}
if (path[0] != '/') {
boolStatus = GetCwdString(path, resultDir, len);
} else {
int32_t ret = strcpy_s(resultDir, len, path);
PROF_CHK_EXPR_ACTION(ret != EOK, return false, "sprintf fail for dir %s.", path);
}
return boolStatus;
}
bool IsDir(const CHAR* path)
{
if (strlen(path) == 0) {
return false;
}
if (OsalIsDir(path) != OSAL_EN_OK) {
return false;
}
return true;
}
bool IsDirAccessible(const CHAR* path)
{
if (!IsDir(path)) {
MSPROF_LOGW("Path %s is not a dir", path);
return false;
}
if (OsalAccess2(path, OSAL_W_OK) == OSAL_EN_OK) {
return true;
}
MSPROF_LOGW("No access to dir %s", path);
return false;
}
bool IsFileExist(const CHAR* path)
{
if (strlen(path) == 0) {
return false;
}
if (OsalAccess(path) == OSAL_EN_OK) {
return true;
}
return false;
}
#endif
#define SELF_PATH_LEN 24U
bool GetSelfPath(CHAR* resultDir)
{
#ifdef LITE_OS
UNUSED(resultDir);
#else
char selfPath[SELF_PATH_LEN];
errno_t ret = EOK;
ret = strcpy_s(selfPath, sizeof(selfPath), "/proc/self/exe");
PROF_CHK_EXPR_ACTION(ret != EOK, return false, "SelfPath strcpy failed.");
int32_t len = (int32_t)(readlink(selfPath, resultDir, OSAL_MAX_PATH));
MSPROF_LOGI("Get self bin directory len: %d", len);
if (len < 0) {
ret = strcpy_s(selfPath, sizeof(selfPath), "/local/proc/self/exe");
PROF_CHK_EXPR_ACTION(ret != EOK, return false, "Local selfPath strcpy failed.");
len = (int32_t)(readlink(selfPath, resultDir, OSAL_MAX_PATH));
}
MSPROF_LOGI("Get proc self bin directory len: %d", len);
if (len < 0 || len > OSAL_MAX_PATH) {
MSPROF_LOGW("Can't Get self bin directory");
return false;
}
#endif
return true;
}
* @brief Enter the desired path. This method will recursively create the path.
* @param [in] resultPath: output path, which is to be created.
* @return success: true
* failed : false
*/
bool CreateDirectory(CHAR* resultPath)
{
#ifdef LITE_OS
UNUSED(resultPath);
return true;
#else
PROF_CHK_EXPR_ACTION(resultPath == NULL, return false, "Input data resultPath is NULL.");
if (strlen(resultPath) == 0) {
MSPROF_LOGW("Input path is empty.");
return false;
}
char tmp[DEFAULT_OUTPUT_MAX_LEGTH] = { 0 };
errno_t ret = strcat_s(tmp, sizeof(tmp), resultPath);
PROF_CHK_EXPR_ACTION(ret != EOK, return false,
"Failed to strcat_s for dir: %s, ret: %d.", resultPath, ret);
char path[DEFAULT_OUTPUT_MAX_LEGTH] = { 0 };
char *context = NULL;
const char *delim = "/";
char *token = Strtok(tmp, delim, &context);
PROF_CHK_EXPR_ACTION(errno == ERANGE, return false,
"The errno is out of the range that can be represented after strtok.");
while (token != NULL) {
ret = strcat_s(path, sizeof(path), delim);
PROF_CHK_EXPR_ACTION(ret != EOK, return false,
"Failed to strcat_s '/' to dir: %s, ret is %d.", resultPath, ret);
ret = strcat_s(path, sizeof(path), token);
PROF_CHK_EXPR_ACTION(ret != EOK, return false,
"Failed to strcat_s token to dir: %s, ret is %d.", resultPath, ret);
token = Strtok(NULL, delim, &context);
PROF_CHK_EXPR_ACTION(errno == ERANGE, return false,
"The errno is out of the range that can be represented in recycling.");
if (IsFileExist(path)) {
MSPROF_LOGD("The file already exists, %s", path);
continue;
}
const OsalMode defaultFileMode = (OsalMode)0750;
if ((OsalMkdir(path, defaultFileMode) != OSAL_EN_OK) && (errno != EEXIST)) {
char errBuf[MAX_ERR_STRING_LEN + 1] = {0};
MSPROF_LOGE("Failed to mkdir, FilePath : %s, FileMode : %o, ErrorCode : %d, ERRORInfo : %s",
path, (int32_t)defaultFileMode, OsalGetErrorCode(),
OsalGetErrorFormatMessage(OsalGetErrorCode(), errBuf, MAX_ERR_STRING_LEN));
return false;
}
}
return true;
#endif
}
bool CheckIsUIntNum(const CHAR* numberStr)
{
char maxUintValStr[] = "4294967295";
return CheckStringNumRange(numberStr, maxUintValStr);
}
bool CheckStringNumRange(const CHAR* numberStr, const CHAR* target)
{
if (strlen(numberStr) == 0) {
return false;
}
if (strlen(numberStr) > strlen(target)) {
MSPROF_LOGE("[CheckStringNumRange] numberStr(%s) is too long than (%s)", numberStr, target);
return false;
}
for (uint32_t j = 0; j < strlen(numberStr); ++j) {
if (numberStr[j] < '0' || numberStr[j] > '9') {
MSPROF_LOGE("[CheckStringNumRange] numberStr(%s) is not a positive integer", numberStr);
return false;
}
}
if (strlen(numberStr) == strlen(target)) {
for (uint32_t i = 0; i < strlen(numberStr); ++i) {
if (numberStr[i] > target[i]) {
MSPROF_LOGE("[CheckStringNumRange] numberStr(%s) is over than %s", numberStr, target);
return false;
} else if (numberStr[i] == target[i]) {
continue;
} else {
break;
}
}
}
return true;
}
* @brief Transfer uint32_t to string, which need to be free by caller
* @param [in] num: uint32_t number
* @return success: str
* failed : NULL
*/
CHAR* TransferUint32ToString(uint32_t num)
{
char* str = (char*)OsalMalloc(sizeof(char) * MAX_NUMBER_LEN);
if (str == NULL) {
return NULL;
}
int32_t ret = sprintf_s(str, MAX_NUMBER_LEN, "%u", num);
if (ret == -1) {
OSAL_MEM_FREE(str);
MSPROF_LOGE("Failed to TransferUint32ToString, ret: %d, num: %u.", ret, num);
return NULL;
}
return str;
}
* @brief Transfer uint64_t to string, which need to be free by caller
* @param [in] num: uint64_t number
* @return success: str
* failed : NULL
*/
CHAR* TransferUint64ToString(uint64_t num)
{
char* strlong = (char*)OsalMalloc(sizeof(char) * MAX_NUMBER_LONG_LEN);
if (strlong == NULL) {
return NULL;
}
int32_t ret = sprintf_s(strlong, MAX_NUMBER_LONG_LEN, "%llu", num);
if (ret == -1) {
OSAL_MEM_FREE(strlong);
MSPROF_LOGE("Failed to TransferUint64ToString, ret: %d, num: %" PRIu64 ".", ret, num);
return NULL;
}
return strlong;
}
* @brief Transfer float to string, which need to be free by caller
* @param [in] num: float number
* @return success: str
* failed : NULL
*/
CHAR* TransferFloatToString(float num)
{
char* strFloat = (char*)OsalMalloc(sizeof(char) * MAX_NUMBER_FLOAT_LEN);
if (strFloat == NULL) {
return NULL;
}
int32_t ret = sprintf_s(strFloat, MAX_NUMBER_FLOAT_LEN, "%.4f", num);
if (ret == -1) {
OSAL_MEM_FREE(strFloat);
MSPROF_LOGE("Failed to TransferFloatToString, ret: %d, num: %.4f.", ret, num);
return NULL;
}
return strFloat;
}
int64_t GetClockMonotonicTime(void)
{
OsalTimespec now = OsalGetTickCount();
return (now.tv_sec) * TRANSFER_FROM_S_TO_NS + now.tv_nsec;
}
uint64_t GetBkdrHashId(const CHAR *str)
{
static const uint64_t SEED = 31;
uint64_t hash = 0;
while (*str != '\0') {
hash = ((hash * SEED) + (uint64_t)(*str)) % UINT64_MAX;
str++;
}
return hash;
}
uint64_t TransferStringToInt(CHAR *nptr, size_t nptrLen, CHAR **endptr, uint64_t base)
{
(void)nptrLen;
uint64_t result = 0;
int32_t sign = 1;
if (*nptr == '-') {
sign = -1;
nptr++;
} else if (*nptr == '+') {
nptr++;
} else {
;
}
while (*nptr >= '0' && *nptr <= '9') {
result = result * base + (uint64_t)(*nptr - '0');
nptr++;
}
if (sign == -1) {
result = -result;
}
if (endptr != NULL) {
*endptr = nptr;
}
return result;
}
double TransferStringToDouble(CHAR *nptr, size_t nptrLen, CHAR **endptr)
{
(void)nptrLen;
double result = 0.0;
int32_t sign = 1;
double baseTen = 10.0;
if (*nptr == '-') {
sign = -1;
nptr++;
}
while (*nptr >= '0' && *nptr <= '9') {
int32_t nums = *nptr - '0';
result = result * baseTen + (double)(nums);
nptr++;
}
if (*nptr == '.') {
nptr++;
double fraction = 0.0;
double base = 0.1;
while (*nptr >= '0' && *nptr <= '9') {
fraction += (double)(*nptr - '0') * base;
base /= baseTen;
nptr++;
}
result += fraction;
}
if (sign == -1) {
result = -result;
}
if (endptr != NULL) {
*endptr = nptr;
}
return result;
}
char *TimestampToTime(uint64_t timestamp, uint32_t unit)
{
PROF_CHK_EXPR_ACTION(unit == 0, return NULL, "TimestampToTime failed, divisor is 0.");
uint32_t microTime = (uint32_t)(timestamp % (uint64_t)unit);
uint64_t tmpTime = timestamp / unit;
PROF_CHK_EXPR_ACTION(tmpTime > LONG_MAX, return NULL,
"Failed to prepare for forced transfer. The data %" PRIu64 " exceeds the long type.", tmpTime);
time_t t = (time_t)tmpTime;
struct tm *lt = localtime(&t);
char* dateStr = (char*)OsalMalloc(sizeof(char) * DATESTR_MAXLEN);
if (dateStr == NULL) {
return NULL;
}
size_t len = strftime(dateStr, DATESTR_MAXLEN, "%Y-%m-%d %H:%M:%S", lt);
if (len == 0) {
MSPROF_LOGE("TimestampToTime, dateStr too short");
}
char *microTimeStr = TransferUint64ToString(microTime);
PROF_CHK_EXPR_ACTION(microTimeStr == NULL,
{OSAL_MEM_FREE(dateStr); return NULL;}, "Failed to transfer microTimeStr.");
int32_t ret = strcat_s(dateStr, DATESTR_MAXLEN, ".");
PROF_CHK_EXPR_ACTION(ret != EOK,
{OSAL_MEM_FREE(dateStr); OSAL_MEM_FREE(microTimeStr); return NULL;}, "Faild to strcat_s for TimestampToTime.");
ret = strcat_s(dateStr, DATESTR_MAXLEN, microTimeStr);
PROF_CHK_EXPR_ACTION(ret != EOK,
{OSAL_MEM_FREE(dateStr); OSAL_MEM_FREE(microTimeStr); return NULL;}, "Faild to strcat_s for TimestampToTime.");
OSAL_MEM_FREE(microTimeStr);
return dateStr;
}
CHAR *Strtok(CHAR *strToken, const CHAR *delimit, CHAR **context)
{
#ifdef LITE_OS
UNUSED(context);
return strtok(strToken, delimit);
#else
return strtok_s(strToken, delimit, context);
#endif
}