* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef USE_NATIVE_TOKEN_KLOG
#include "accesstoken_klog.h"
#else
#include "accesstoken_common_log.h"
#endif
#include <cstdlib>
#include <cstdio>
#include <cstdarg>
#include <cstdint>
#include <cstring>
#include <string>
#include "securec.h"
static constexpr uint32_t MAX_ERROR_MESSAGE_LEN = 4096;
static __thread uint32_t g_msgLen = 0;
static __thread char g_errMsg[MAX_ERROR_MESSAGE_LEN + 1];
#ifdef USE_NATIVE_TOKEN_KLOG
#define ACCESSTOKEN_COMMON_LOGE(domain, tag, fmt, ...) \
((void)LOGE(fmt, ##__VA_ARGS__))
#else
#define ACCESSTOKEN_COMMON_LOGE(domain, tag, fmt, ...) \
((void)LOGE(domain, tag, fmt, ##__VA_ARGS__))
#endif
uint32_t GetThreadErrorMsgLen(void)
{
return g_msgLen;
}
const char* GetThreadErrorMsg(void)
{
return g_errMsg;
}
void ClearThreadErrorMsg(void)
{
(void)memset_s(g_errMsg, MAX_ERROR_MESSAGE_LEN + 1, 0, MAX_ERROR_MESSAGE_LEN + 1);
g_msgLen = 0;
}
static bool ReplaceSubstring(unsigned int domain, const char* tag,
const char* format, char result[MAX_ERROR_MESSAGE_LEN])
{
std::string formatString(format);
#ifndef USE_NATIVE_TOKEN_KLOG
std::string::size_type pos;
while ((pos = formatString.find(LOG_PUBLIC)) != std::string::npos) {
formatString.replace(pos, strlen(LOG_PUBLIC), "");
}
#endif
if (memcpy_s(result, MAX_ERROR_MESSAGE_LEN, formatString.c_str(), formatString.size()) != EOK) {
return false;
}
return true;
}
void AddEventMessage(unsigned int domain, const char* tag,
const char* format, ...)
{
va_list ap;
if (g_msgLen == 0) {
char newFormat[MAX_ERROR_MESSAGE_LEN] = {0};
if (!ReplaceSubstring(domain, tag, format, newFormat)) {
ACCESSTOKEN_COMMON_LOGE(domain, tag, "Skip to add errMsg");
return;
}
va_start(ap, format);
char buff[MAX_ERROR_MESSAGE_LEN] = {0};
int32_t buffLen = vsnprintf_s(buff, MAX_ERROR_MESSAGE_LEN, MAX_ERROR_MESSAGE_LEN - 1, newFormat, ap);
va_end(ap);
if (buffLen < 0) {
ACCESSTOKEN_COMMON_LOGE(domain, tag,
"Failed to vsnprintf_s! Ret: %" LOG_PUBLIC "d, newFormat:[%" LOG_PUBLIC "s]", buffLen, newFormat);
return;
}
if (g_msgLen + static_cast<uint32_t>(buffLen) >= MAX_ERROR_MESSAGE_LEN) {
ACCESSTOKEN_COMMON_LOGE(domain, tag, "ErrMsg is almost full!");
return;
}
if (memcpy_s(g_errMsg + g_msgLen, MAX_ERROR_MESSAGE_LEN, buff, buffLen) != EOK) {
ACCESSTOKEN_COMMON_LOGE(domain, tag, "Failed to copy errMsg buff!");
return;
}
g_msgLen += static_cast<uint32_t>(buffLen);
} else {
va_start(ap, format);
char* funName = va_arg(ap, char*);
uint32_t lineNo = va_arg(ap, uint32_t);
va_end(ap);
if (funName == nullptr) {
ACCESSTOKEN_COMMON_LOGE(domain, tag, "Get funName fail!");
return;
}
int32_t offset = sprintf_s(g_errMsg + g_msgLen, MAX_ERROR_MESSAGE_LEN - g_msgLen, " <%s[%u]",
funName, lineNo);
if (offset <= 0) {
ACCESSTOKEN_COMMON_LOGE(domain, tag, "Failed to append call chain! Offset: [%" LOG_PUBLIC "d]", offset);
return;
}
g_msgLen += static_cast<uint32_t>(offset);
}
}