diff --git a/0001-init-and-adapt-to-openeuler.patch b/0001-init-and-adapt-to-openeuler.patch new file mode 100644 index 0000000000000000000000000000000000000000..8faea2e9f21ccf1c683104eb40439613f7ea9baf --- /dev/null +++ b/0001-init-and-adapt-to-openeuler.patch @@ -0,0 +1,4056 @@ +From 4611bb6a513f43fee84946994d5b5fe05e341c16 Mon Sep 17 00:00:00 2001 +From: tian2020 +Date: Wed, 14 Jun 2023 17:32:44 +0800 +Subject: [PATCH 1/3] init and adapt to openeuler + +--- + frameworks/libhilog/BUILD.gn | 101 +- + frameworks/libhilog/base/hilog_base.cpp | 535 +++---- + frameworks/libhilog/hilog.cpp | 121 +- + frameworks/libhilog/hilog_printf.cpp | 3 +- + frameworks/libhilog/include/hilog_cmd.h | 2 +- + frameworks/libhilog/utils/include/log_print.h | 94 +- + frameworks/libhilog/utils/include/log_utils.h | 220 +-- + frameworks/libhilog/utils/log_print.cpp | 360 ++--- + frameworks/libhilog/utils/log_utils.cpp | 1044 ++++++------- + .../libhilog/vsnprintf/include/output_p.inl | 1294 +++++++++++++++++ + hilog.gni | 6 +- + interfaces/bundle.json | 5 +- + interfaces/native/innerkits/BUILD.gn | 41 +- + .../native/innerkits/include/hilog/log_c.h | 4 +- + .../native/innerkits/include/hilog/log_cpp.h | 17 +- + 15 files changed, 2590 insertions(+), 1257 deletions(-) + create mode 100644 frameworks/libhilog/vsnprintf/include/output_p.inl + +diff --git a/frameworks/libhilog/BUILD.gn b/frameworks/libhilog/BUILD.gn +index fe1a662..f8372a9 100644 +--- a/frameworks/libhilog/BUILD.gn ++++ b/frameworks/libhilog/BUILD.gn +@@ -39,78 +39,33 @@ config("libhilog_config") { + ] + } + +-template("libhilog_source") { +- forward_variables_from(invoker, "*") +- ohos_source_set(target_name) { +- if (platform != "windows" && platform != "mac" && platform != "linux") { +- param_sources = [ "$param_root/properties.cpp" ] +- ioctl_sources = [ "$ioctl_root/log_ioctl.cpp" ] +- +- socket_sources = [ +- "$socket_root/dgram_socket_client.cpp", +- "$socket_root/dgram_socket_server.cpp", +- "$socket_root/hilog_input_socket_client.cpp", +- "$socket_root/hilog_input_socket_server.cpp", +- "$socket_root/seq_packet_socket_client.cpp", +- "$socket_root/seq_packet_socket_server.cpp", +- "$socket_root/socket.cpp", +- "$socket_root/socket_client.cpp", +- "$socket_root/socket_server.cpp", +- ] +- } +- +- utils_sources = [ +- "$utils_root/log_print.cpp", +- "$utils_root/log_utils.cpp", +- ] +- +- vsnprintf_sources = [ "$vsnprintf_root/vsnprintf_s_p.cpp" ] +- +- sources = [ +- "hilog.cpp", +- "hilog_printf.cpp", +- ] +- if (platform != "windows" && platform != "mac" && platform != "linux") { +- sources += param_sources +- sources += ioctl_sources +- sources += socket_sources +- } +- sources += utils_sources +- sources += vsnprintf_sources +- +- defines = [] +- if (platform == "windows") { +- cflags_cc = [ "-std=c++17" ] +- defines += [ "__WINDOWS__" ] +- } else if (platform == "mac") { +- defines += [ "__MAC__" ] +- } else if (platform == "linux") { +- cflags_cc = [ "-std=c++17" ] +- defines += [ "__LINUX__" ] +- } else { +- defines = [ "__RECV_MSG_WITH_UCRED_" ] +- if (use_musl) { +- defines += [ "HILOG_USE_MUSL" ] +- } +- } +- public_configs = [ ":libhilog_config" ] +- configs = [ ":libhilog_config" ] +- +- deps = [ "//third_party/bounds_checking_function:libsec_shared" ] +- +- if (platform != "windows" && platform != "mac" && platform != "linux") { +- external_deps = [ "init:libbegetutil" ] +- } +- +- part_name = "hilog_native" +- subsystem_name = "hiviewdfx" +- } +-} ++ohos_source_set("libhilog_source") { ++ ++ utils_sources = [ ++ "$utils_root/log_print.cpp", ++ "$utils_root/log_utils.cpp", ++ ] ++ ++ vsnprintf_sources = [ "$vsnprintf_root/vsnprintf_s_p.cpp" ] ++ ++ sources = [ ++ "hilog.cpp", ++ "hilog_printf.cpp", ++ ] ++ sources += utils_sources ++ sources += vsnprintf_sources + +-foreach(item, platforms) { +- libhilog_source("libhilog_source_" + item) { +- platform = item +- } ++ defines = [] ++ cflags_cc = [ "-std=c++17" ] ++ defines += [ "__LINUX__" ] ++ ++ public_configs = [ ":libhilog_config" ] ++ configs = [ ":libhilog_config" ] ++ ++ deps = [ "//third_party/bounds_checking_function:libsec_shared" ] ++ ++ part_name = "hilog_native" ++ subsystem_name = "hiviewdfx" + } + + config("libhilog_base_config") { +@@ -124,10 +79,10 @@ ohos_source_set("libhilog_base_source") { + "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", + ] + +- vsnprintf_sources = [ "$vsnprintf_root/vsnprintf_s_p.cpp" ] ++ # vsnprintf_sources = [ "$vsnprintf_root/vsnprintf_s_p.cpp" ] + + sources = [ "$libhilog_base_root/hilog_base.cpp" ] +- sources += vsnprintf_sources ++ # sources += vsnprintf_sources + + defines = [ + "__RECV_MSG_WITH_UCRED_", +diff --git a/frameworks/libhilog/base/hilog_base.cpp b/frameworks/libhilog/base/hilog_base.cpp +index 8e8e248..85337b8 100644 +--- a/frameworks/libhilog/base/hilog_base.cpp ++++ b/frameworks/libhilog/base/hilog_base.cpp +@@ -16,279 +16,280 @@ + #include "hilog_base/log_base.h" + + #include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-namespace { +-constexpr int SOCKET_TYPE = SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC; +-constexpr int INVALID_SOCKET = -1; +-constexpr size_t HILOG_VEC_MAX_SIZE = 4; +-constexpr size_t HILOG_VEC_SIZE_OHCORE = 4; +-constexpr size_t HILOG_VEC_SIZE_OH = 3; +-constexpr int32_t MAX_DOMAIN_TAGSIZE = 64; +- +-struct SocketHandler { +- std::atomic_int socketFd {INVALID_SOCKET}; +- std::atomic_bool isConnected {false}; +- ~SocketHandler() +- { +- int currentFd = socketFd.exchange(INVALID_SOCKET); +- if (currentFd >= 0) { +- close(currentFd); +- } +- } +-}; +- +-typedef struct LogTime { +- uint32_t tvSec; +- uint32_t tvNsec; +-} __attribute__((__packed__)) LogTime; +- +-typedef struct __attribute__((__packed__)) { +- uint8_t id; +- uint16_t tid; +- uint16_t ohPid; +- LogTime realtime; +-} LogHeader; +- +-struct HiLogMsgInfo { +- HilogMsg *header_; +- const char *tag_; +- uint16_t tagLen_; +- const char *fmt_; +- uint16_t fmtLen_; +- HiLogMsgInfo(HilogMsg *header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen) +- { +- header_ = header; +- tag_ = tag; +- tagLen_ = tagLen; +- fmt_ = fmt; +- fmtLen_ = fmtLen; +- } +-}; +- +-typedef enum { +- TYPE_OH = 0, +- TYPE_OHCORE = 1, +-} HiLogProtocolType; +- +-sockaddr_un g_sockAddr = {AF_UNIX, SOCKET_FILE_DIR INPUT_SOCKET_NAME}; +-HiLogProtocolType g_protocolType = TYPE_OH; +- +-struct Initializer { +- Initializer() +- { +- constexpr char configFile[] = "/system/etc/hilog_config"; +- if (access(configFile, F_OK) != 0) { +- return; +- } +- std::ifstream file; +- file.open(configFile); +- if (file.fail()) { +- std::cerr << "open hilog_config config file failed" << std::endl; +- return; +- } +- +- std::string sock; +- std::string protocol; +- file >> sock >> protocol; +- if (auto posColon = sock.find(":"); posColon != sock.npos) { +- std::string sockPath = sock.substr(posColon + 1); +- size_t pos = 0; +- while (pos < sockPath.size() && pos < (sizeof(g_sockAddr.sun_path) - 1)) { +- g_sockAddr.sun_path[pos] = sockPath[pos]; +- pos++; +- } +- g_sockAddr.sun_path[pos] = '\0'; +- } +- if (auto posColon = protocol.find(":"); posColon != protocol.npos) { +- g_protocolType = protocol.substr(posColon + 1) == "ohcore" ? TYPE_OHCORE : TYPE_OH; +- } +- file.close(); +- } +-}; +-Initializer g_initializer; +- +-static int GenerateFD() +-{ +- int tmpFd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCKET_TYPE, 0)); +- int res = tmpFd; +- if (tmpFd == 0) { +- res = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCKET_TYPE, 0)); +- close(tmpFd); +- } +- return res; +-} +- +-static int CheckSocket(SocketHandler& socketHandler) +-{ +- int currentFd = socketHandler.socketFd.load(); +- if (currentFd >= 0) { +- return currentFd; +- } +- +- int fd = GenerateFD(); +- if (fd < 0) { +- std::cerr << "Can't get hilog socket! Errno: " << errno << std::endl; +- return fd; +- } +- +- currentFd = INVALID_SOCKET; +- if (!socketHandler.socketFd.compare_exchange_strong(currentFd, fd)) { +- close(fd); +- return currentFd; +- } +- return fd; +-} +- +-static int CheckConnection(SocketHandler& socketHandler) +-{ +- bool isConnected = socketHandler.isConnected.load(); +- if (isConnected) { +- return 0; +- } +- +- isConnected = socketHandler.isConnected.load(); +- if (isConnected) { +- return 0; +- } +- +- auto result = TEMP_FAILURE_RETRY(connect(socketHandler.socketFd.load(), +- reinterpret_cast(&g_sockAddr), sizeof(g_sockAddr))); +- if (result < 0) { +- std::cerr << "Can't connect to hilog server. Errno: " << errno << std::endl; +- return result; +- } +- socketHandler.isConnected.store(true); +- return 0; +-} +- +-static size_t BuildHilogMessageForOhCore(struct HiLogMsgInfo* logMsgInfo, LogHeader& logHeader, uint16_t& logLevel, +- char tagBuf[], struct iovec *vec) +-{ +- struct timespec ts = {0}; +- (void)clock_gettime(CLOCK_REALTIME, &ts); +- logHeader.realtime.tvSec = static_cast(ts.tv_sec); +- logHeader.realtime.tvNsec = static_cast(ts.tv_nsec); +- logHeader.tid = static_cast(gettid()); +- logHeader.ohPid = static_cast(getpid()); +- logLevel = logMsgInfo->header_->level; +- constexpr uint32_t domainFilter = 0x000FFFFF; +- if (vsnprintfp_s(tagBuf, MAX_DOMAIN_TAGSIZE, MAX_DOMAIN_TAGSIZE - 1, false, "%05X/%s", +- (logMsgInfo->header_->domain & domainFilter), logMsgInfo->tag_) < 0) { +- return 0; +- } +- +- vec[0].iov_base = reinterpret_cast(&logHeader); // 0 : index of hos log header +- vec[0].iov_len = sizeof(logHeader); // 0 : index of hos log header +- vec[1].iov_base = reinterpret_cast(&logLevel); // 1 : index of log level +- vec[1].iov_len = 1; // 1 : index of log level +- vec[2].iov_base = reinterpret_cast(const_cast(tagBuf)); // 2 : index of log tag +- vec[2].iov_len = strlen(tagBuf) + 1; // 2 : index of log tag +- vec[3].iov_base = reinterpret_cast(const_cast(logMsgInfo->fmt_)); // 3 : index of log format +- vec[3].iov_len = logMsgInfo->fmtLen_; // 3 : index of log format +- return HILOG_VEC_SIZE_OHCORE; +-} +- +-static size_t BuildHilogMessageForOh(struct HiLogMsgInfo* logMsgInfo, struct iovec *vec) +-{ +- struct timespec ts = {0}; +- (void)clock_gettime(CLOCK_REALTIME, &ts); +- struct timespec tsMono = {0}; +- (void)clock_gettime(CLOCK_MONOTONIC, &tsMono); +- logMsgInfo->header_->tv_sec = static_cast(ts.tv_sec); +- logMsgInfo->header_->tv_nsec = static_cast(ts.tv_nsec); +- logMsgInfo->header_->mono_sec = static_cast(tsMono.tv_sec); +- logMsgInfo->header_->len = sizeof(HilogMsg) + logMsgInfo->tagLen_ + logMsgInfo->fmtLen_; +- logMsgInfo->header_->tag_len = logMsgInfo->tagLen_; +- +- vec[0].iov_base = logMsgInfo->header_; // 0 : index of hos log header +- vec[0].iov_len = sizeof(HilogMsg); // 0 : index of hos log header +- vec[1].iov_base = reinterpret_cast(const_cast(logMsgInfo->tag_)); // 1 : index of log tag +- vec[1].iov_len = logMsgInfo->tagLen_; // 1 : index of log tag +- vec[2].iov_base = reinterpret_cast(const_cast(logMsgInfo->fmt_)); // 2 : index of log content +- vec[2].iov_len = logMsgInfo->fmtLen_; // 2 : index of log content +- return HILOG_VEC_SIZE_OH; +-} +- +-static int SendMessage(HilogMsg *header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen) +-{ +- SocketHandler socketHandler; +- int ret = CheckSocket(socketHandler); +- if (ret < 0) { +- return ret; +- } +- ret = CheckConnection(socketHandler); +- if (ret < 0) { +- return ret; +- } +- +- struct iovec vec[HILOG_VEC_MAX_SIZE]; +- struct HiLogMsgInfo msgInfo(header, tag, tagLen, fmt, fmtLen); +- LogHeader logHeader; +- uint16_t logLevel = 0; +- char tagBuf[MAX_DOMAIN_TAGSIZE] = {0}; +- auto vecSize = (g_protocolType == TYPE_OHCORE) ? +- BuildHilogMessageForOhCore(&msgInfo, logHeader, logLevel, tagBuf, vec) : +- BuildHilogMessageForOh(&msgInfo, vec); +- if (vecSize == 0) { +- std::cerr << "BuildHilogMessage failed ret = " << vecSize << std::endl; +- return RET_FAIL; +- } +- return TEMP_FAILURE_RETRY(::writev(socketHandler.socketFd.load(), vec, vecSize)); +-} +- +-static int HiLogBasePrintArgs(const LogType type, const LogLevel level, const unsigned int domain, const char *tag, +- const char *fmt, va_list ap) +-{ +- if (!HiLogBaseIsLoggable(domain, tag, level)) { +- return -1; +- } +- +- char buf[MAX_LOG_LEN] = {0}; +- +- vsnprintfp_s(buf, MAX_LOG_LEN, MAX_LOG_LEN - 1, true, fmt, ap); +- +- auto tagLen = strnlen(tag, MAX_TAG_LEN - 1); +- auto logLen = strnlen(buf, MAX_LOG_LEN - 1); +- HilogMsg header = {0}; +- header.type = type; +- header.level = level; +-#ifndef __RECV_MSG_WITH_UCRED_ +- header.pid = getpid(); +-#endif +- header.tid = static_cast(gettid()); +- header.domain = domain; +- +- return SendMessage(&header, tag, tagLen + 1, buf, logLen + 1); +-} +- +-} // namespace ++// #include ++ ++// #include ++// #include ++// #include ++// #include ++// #include ++// #include ++// #include ++// #include ++// #include ++// #include ++ ++// namespace { ++// constexpr int SOCKET_TYPE = SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC; ++// constexpr int INVALID_SOCKET = -1; ++// constexpr size_t HILOG_VEC_MAX_SIZE = 4; ++// constexpr size_t HILOG_VEC_SIZE_OHCORE = 4; ++// constexpr size_t HILOG_VEC_SIZE_OH = 3; ++// constexpr int32_t MAX_DOMAIN_TAGSIZE = 64; ++ ++// struct SocketHandler { ++// std::atomic_int socketFd {INVALID_SOCKET}; ++// std::atomic_bool isConnected {false}; ++// ~SocketHandler() ++// { ++// int currentFd = socketFd.exchange(INVALID_SOCKET); ++// if (currentFd >= 0) { ++// close(currentFd); ++// } ++// } ++// }; ++ ++// typedef struct LogTime { ++// uint32_t tvSec; ++// uint32_t tvNsec; ++// } __attribute__((__packed__)) LogTime; ++ ++// typedef struct __attribute__((__packed__)) { ++// uint8_t id; ++// uint16_t tid; ++// uint16_t ohPid; ++// LogTime realtime; ++// } LogHeader; ++ ++// struct HiLogMsgInfo { ++// HilogMsg *header_; ++// const char *tag_; ++// uint16_t tagLen_; ++// const char *fmt_; ++// uint16_t fmtLen_; ++// HiLogMsgInfo(HilogMsg *header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen) ++// { ++// header_ = header; ++// tag_ = tag; ++// tagLen_ = tagLen; ++// fmt_ = fmt; ++// fmtLen_ = fmtLen; ++// } ++// }; ++ ++// typedef enum { ++// TYPE_OH = 0, ++// TYPE_OHCORE = 1, ++// } HiLogProtocolType; ++ ++// sockaddr_un g_sockAddr = {AF_UNIX, SOCKET_FILE_DIR INPUT_SOCKET_NAME}; ++// HiLogProtocolType g_protocolType = TYPE_OH; ++ ++// struct Initializer { ++// Initializer() ++// { ++// constexpr char configFile[] = "/system/etc/hilog_config"; ++// if (access(configFile, F_OK) != 0) { ++// return; ++// } ++// std::ifstream file; ++// file.open(configFile); ++// if (file.fail()) { ++// std::cerr << "open hilog_config config file failed" << std::endl; ++// return; ++// } ++ ++// std::string sock; ++// std::string protocol; ++// file >> sock >> protocol; ++// if (auto posColon = sock.find(":"); posColon != sock.npos) { ++// std::string sockPath = sock.substr(posColon + 1); ++// size_t pos = 0; ++// while (pos < sockPath.size() && pos < (sizeof(g_sockAddr.sun_path) - 1)) { ++// g_sockAddr.sun_path[pos] = sockPath[pos]; ++// pos++; ++// } ++// g_sockAddr.sun_path[pos] = '\0'; ++// } ++// if (auto posColon = protocol.find(":"); posColon != protocol.npos) { ++// g_protocolType = protocol.substr(posColon + 1) == "ohcore" ? TYPE_OHCORE : TYPE_OH; ++// } ++// file.close(); ++// } ++// }; ++// Initializer g_initializer; ++ ++// static int GenerateFD() ++// { ++// int tmpFd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCKET_TYPE, 0)); ++// int res = tmpFd; ++// if (tmpFd == 0) { ++// res = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCKET_TYPE, 0)); ++// close(tmpFd); ++// } ++// return res; ++// } ++ ++// static int CheckSocket(SocketHandler& socketHandler) ++// { ++// int currentFd = socketHandler.socketFd.load(); ++// if (currentFd >= 0) { ++// return currentFd; ++// } ++ ++// int fd = GenerateFD(); ++// if (fd < 0) { ++// std::cerr << "Can't get hilog socket! Errno: " << errno << std::endl; ++// return fd; ++// } ++ ++// currentFd = INVALID_SOCKET; ++// if (!socketHandler.socketFd.compare_exchange_strong(currentFd, fd)) { ++// close(fd); ++// return currentFd; ++// } ++// return fd; ++// } ++ ++// static int CheckConnection(SocketHandler& socketHandler) ++// { ++// bool isConnected = socketHandler.isConnected.load(); ++// if (isConnected) { ++// return 0; ++// } ++ ++// isConnected = socketHandler.isConnected.load(); ++// if (isConnected) { ++// return 0; ++// } ++ ++// auto result = TEMP_FAILURE_RETRY(connect(socketHandler.socketFd.load(), ++// reinterpret_cast(&g_sockAddr), sizeof(g_sockAddr))); ++// if (result < 0) { ++// std::cerr << "Can't connect to hilog server. Errno: " << errno << std::endl; ++// return result; ++// } ++// socketHandler.isConnected.store(true); ++// return 0; ++// } ++ ++// static size_t BuildHilogMessageForOhCore(struct HiLogMsgInfo* logMsgInfo, LogHeader& logHeader, uint16_t& logLevel, ++// char tagBuf[], struct iovec *vec) ++// { ++// struct timespec ts = {0}; ++// (void)clock_gettime(CLOCK_REALTIME, &ts); ++// logHeader.realtime.tvSec = static_cast(ts.tv_sec); ++// logHeader.realtime.tvNsec = static_cast(ts.tv_nsec); ++// logHeader.tid = static_cast(gettid()); ++// logHeader.ohPid = static_cast(getpid()); ++// logLevel = logMsgInfo->header_->level; ++// constexpr uint32_t domainFilter = 0x000FFFFF; ++// if (vsnprintfp_s(tagBuf, MAX_DOMAIN_TAGSIZE, MAX_DOMAIN_TAGSIZE - 1, false, "%05X/%s", ++// (logMsgInfo->header_->domain & domainFilter), logMsgInfo->tag_) < 0) { ++// return 0; ++// } ++ ++// vec[0].iov_base = reinterpret_cast(&logHeader); // 0 : index of hos log header ++// vec[0].iov_len = sizeof(logHeader); // 0 : index of hos log header ++// vec[1].iov_base = reinterpret_cast(&logLevel); // 1 : index of log level ++// vec[1].iov_len = 1; // 1 : index of log level ++// vec[2].iov_base = reinterpret_cast(const_cast(tagBuf)); // 2 : index of log tag ++// vec[2].iov_len = strlen(tagBuf) + 1; // 2 : index of log tag ++// vec[3].iov_base = reinterpret_cast(const_cast(logMsgInfo->fmt_)); // 3 : index of log format ++// vec[3].iov_len = logMsgInfo->fmtLen_; // 3 : index of log format ++// return HILOG_VEC_SIZE_OHCORE; ++// } ++ ++// static size_t BuildHilogMessageForOh(struct HiLogMsgInfo* logMsgInfo, struct iovec *vec) ++// { ++// struct timespec ts = {0}; ++// (void)clock_gettime(CLOCK_REALTIME, &ts); ++// struct timespec tsMono = {0}; ++// (void)clock_gettime(CLOCK_MONOTONIC, &tsMono); ++// logMsgInfo->header_->tv_sec = static_cast(ts.tv_sec); ++// logMsgInfo->header_->tv_nsec = static_cast(ts.tv_nsec); ++// logMsgInfo->header_->mono_sec = static_cast(tsMono.tv_sec); ++// logMsgInfo->header_->len = sizeof(HilogMsg) + logMsgInfo->tagLen_ + logMsgInfo->fmtLen_; ++// logMsgInfo->header_->tag_len = logMsgInfo->tagLen_; ++ ++// vec[0].iov_base = logMsgInfo->header_; // 0 : index of hos log header ++// vec[0].iov_len = sizeof(HilogMsg); // 0 : index of hos log header ++// vec[1].iov_base = reinterpret_cast(const_cast(logMsgInfo->tag_)); // 1 : index of log tag ++// vec[1].iov_len = logMsgInfo->tagLen_; // 1 : index of log tag ++// vec[2].iov_base = reinterpret_cast(const_cast(logMsgInfo->fmt_)); // 2 : index of log content ++// vec[2].iov_len = logMsgInfo->fmtLen_; // 2 : index of log content ++// return HILOG_VEC_SIZE_OH; ++// } ++ ++// static int SendMessage(HilogMsg *header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen) ++// { ++// SocketHandler socketHandler; ++// int ret = CheckSocket(socketHandler); ++// if (ret < 0) { ++// return ret; ++// } ++// ret = CheckConnection(socketHandler); ++// if (ret < 0) { ++// return ret; ++// } ++ ++// struct iovec vec[HILOG_VEC_MAX_SIZE]; ++// struct HiLogMsgInfo msgInfo(header, tag, tagLen, fmt, fmtLen); ++// LogHeader logHeader; ++// uint16_t logLevel = 0; ++// char tagBuf[MAX_DOMAIN_TAGSIZE] = {0}; ++// auto vecSize = (g_protocolType == TYPE_OHCORE) ? ++// BuildHilogMessageForOhCore(&msgInfo, logHeader, logLevel, tagBuf, vec) : ++// BuildHilogMessageForOh(&msgInfo, vec); ++// if (vecSize == 0) { ++// std::cerr << "BuildHilogMessage failed ret = " << vecSize << std::endl; ++// return RET_FAIL; ++// } ++// return TEMP_FAILURE_RETRY(::writev(socketHandler.socketFd.load(), vec, vecSize)); ++// } ++ ++// static int HiLogBasePrintArgs(const LogType type, const LogLevel level, const unsigned int domain, const char *tag, ++// const char *fmt, va_list ap) ++// { ++// if (!HiLogBaseIsLoggable(domain, tag, level)) { ++// return -1; ++// } ++ ++// char buf[MAX_LOG_LEN] = {0}; ++ ++// vsnprintfp_s(buf, MAX_LOG_LEN, MAX_LOG_LEN - 1, true, fmt, ap); ++ ++// auto tagLen = strnlen(tag, MAX_TAG_LEN - 1); ++// auto logLen = strnlen(buf, MAX_LOG_LEN - 1); ++// HilogMsg header = {0}; ++// header.type = type; ++// header.level = level; ++// #ifndef __RECV_MSG_WITH_UCRED_ ++// header.pid = getpid(); ++// #endif ++// header.tid = static_cast(gettid()); ++// header.domain = domain; ++ ++// return SendMessage(&header, tag, tagLen + 1, buf, logLen + 1); ++// } ++ ++// } // namespace + + int HiLogBasePrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) + { +- int ret; +- va_list ap; +- va_start(ap, fmt); +- ret = HiLogBasePrintArgs(type, level, domain, tag, fmt, ap); +- va_end(ap); +- return ret; ++ // int ret; ++ // va_list ap; ++ // va_start(ap, fmt); ++ // ret = HiLogBasePrintArgs(type, level, domain, tag, fmt, ap); ++ // va_end(ap); ++ // return ret; ++ return 0; + } + + bool HiLogBaseIsLoggable(unsigned int domain, const char *tag, LogLevel level) + { +- if ((level <= LOG_LEVEL_MIN) || (level >= LOG_LEVEL_MAX) || tag == nullptr) { +- return false; +- } ++ // if ((level <= LOG_LEVEL_MIN) || (level >= LOG_LEVEL_MAX) || tag == nullptr) { ++ // return false; ++ // } + return true; + } +diff --git a/frameworks/libhilog/hilog.cpp b/frameworks/libhilog/hilog.cpp +index 80980cb..e58c6d6 100644 +--- a/frameworks/libhilog/hilog.cpp ++++ b/frameworks/libhilog/hilog.cpp +@@ -1,23 +1,26 @@ +-/* +- * Copyright (c) 2021 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. +- */ +- + #include "hilog/log.h" +-#include "hilog_inner.h" + ++#include + #include + #include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "log_utils.h" ++#include "hilog_common.h" ++#include "log_timestamp.h" ++#include "vsnprintf_s_p.h" ++#include "log_print.h" ++ ++using namespace std; ++using namespace OHOS::HiviewDFX; + + namespace OHOS { + namespace HiviewDFX { +@@ -29,6 +32,82 @@ namespace HiviewDFX { + va_end(args); \ + } while (0) + ++int HiPrintLog(HilogMsg& header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen) ++{ ++ LogContent content = { ++ .level = header.level, ++ .type = header.type, ++ .pid = header.pid, ++ .tid = header.tid, ++ .domain = header.domain, ++ .tv_sec = header.tv_sec, ++ .tv_nsec = header.tv_nsec, ++ .mono_sec = header.mono_sec, ++ .tag = tag, ++ .log = fmt, ++ }; ++ LogFormat format = { ++ .colorful = false, ++ .timeFormat = FormatTime::TIME, ++ .timeAccuFormat = FormatTimeAccu::MSEC, ++ .year = false, ++ .zone = false, ++ }; ++ LogPrintWithFormat(content, format); ++ return RET_SUCCESS; ++} ++ ++int HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int domain, const char *tag, ++ const char *fmt, va_list ap) ++{ ++ if ((tag == nullptr)) { ++ return -1; ++ } ++ ++ HilogMsg header = {0}; ++ struct timespec ts = {0}; ++ (void)clock_gettime(CLOCK_REALTIME, &ts); ++ struct timespec ts_mono = {0}; ++ (void)clock_gettime(CLOCK_MONOTONIC, &ts_mono); ++ header.tv_sec = static_cast(ts.tv_sec); ++ header.tv_nsec = static_cast(ts.tv_nsec); ++ header.mono_sec = static_cast(ts_mono.tv_sec); ++ ++ char buf[MAX_LOG_LEN] = {0}; ++ char *logBuf = buf; ++ int traceBufLen = 0; ++ int ret; ++ bool priv = true; ++ ++#ifdef __clang__ ++/* code specific to clang compiler */ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wformat-nonliteral" ++#elif __GNUC__ ++/* code for GNU C compiler */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wformat-nonliteral" ++#endif ++ ret = vsnprintfp_s(logBuf, MAX_LOG_LEN - traceBufLen, MAX_LOG_LEN - traceBufLen - 1, priv, fmt, ap); ++#ifdef __clang__ ++#pragma clang diagnostic pop ++#elif __GNUC__ ++#pragma GCC diagnostic pop ++#endif ++ ++ /* fill header info */ ++ auto tagLen = strnlen(tag, MAX_TAG_LEN - 1); ++ auto logLen = strnlen(buf, MAX_LOG_LEN - 1); ++ header.type = type; ++ header.level = level; ++ header.pid = getpid(); ++ header.tid = static_cast(syscall(SYS_gettid)); ++ header.domain = domain; ++ ++ return HiPrintLog(header, tag, tagLen + 1, buf, logLen + 1); ++ ++} ++ + int HiLog::Debug(const HiLogLabel &label, const char *fmt, ...) + { + int ret; +@@ -65,3 +144,13 @@ int HiLog::Fatal(const HiLogLabel &label, const char *fmt, ...) + } + } // namespace HiviewDFX + } // namespace OHOS ++ ++int HiLogPrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) ++{ ++ int ret; ++ va_list ap; ++ va_start(ap, fmt); ++ ret = HiLogPrintArgs(type, level, domain, tag, fmt, ap); ++ va_end(ap); ++ return ret; ++} +diff --git a/frameworks/libhilog/hilog_printf.cpp b/frameworks/libhilog/hilog_printf.cpp +index 9db1742..1316128 100644 +--- a/frameworks/libhilog/hilog_printf.cpp ++++ b/frameworks/libhilog/hilog_printf.cpp +@@ -55,8 +55,7 @@ static atomic_int g_hiLogGetIdCallCount = 0; + // protected by static lock guard + static char g_hiLogLastFatalMessage[MAX_LOG_LEN] = { 0 }; // MAX_lOG_LEN : 1024 + +-HILOG_PUBLIC_API +-extern "C" const char* GetLastFatalMessage() ++extern "C" HILOG_PUBLIC_API const char* GetLastFatalMessage() + { + return g_hiLogLastFatalMessage; + } +diff --git a/frameworks/libhilog/include/hilog_cmd.h b/frameworks/libhilog/include/hilog_cmd.h +index 1043e1b..677da27 100644 +--- a/frameworks/libhilog/include/hilog_cmd.h ++++ b/frameworks/libhilog/include/hilog_cmd.h +@@ -258,4 +258,4 @@ struct KmsgEnableRqst { + struct KmsgEnableRsp { + char placeholder; + } __attribute__((__packed__)); +-#endif /* HILOG_CMD_H */ +\ No newline at end of file ++#endif /* HILOG_CMD_H */ +diff --git a/frameworks/libhilog/utils/include/log_print.h b/frameworks/libhilog/utils/include/log_print.h +index a84cdc5..e90626a 100644 +--- a/frameworks/libhilog/utils/include/log_print.h ++++ b/frameworks/libhilog/utils/include/log_print.h +@@ -1,47 +1,47 @@ +-/* +- * Copyright (c) 2022 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. +- */ +-#ifndef LOG_PRINT_H +-#define LOG_PRINT_H +-#include +- +-#include "hilog_cmd.h" +- +-namespace OHOS { +-namespace HiviewDFX { +-struct LogContent { +- uint8_t level; +- uint8_t type; +- uint32_t pid; +- uint32_t tid; +- uint32_t domain; +- uint32_t tv_sec; +- uint32_t tv_nsec; +- uint32_t mono_sec; +- const char *tag; +- const char *log; +-}; +- +-struct LogFormat { +- bool colorful; +- FormatTime timeFormat; +- FormatTimeAccu timeAccuFormat; +- bool year; +- bool zone; +-}; +- +-void LogPrintWithFormat(const LogContent& content, const LogFormat& format, std::ostream& out = std::cout); +-} // namespace HiviewDFX +-} // namespace OHOS +-#endif /* LOG_PRINT_H */ +\ No newline at end of file ++/* ++ * Copyright (c) 2022 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. ++ */ ++#ifndef LOG_PRINT_H ++#define LOG_PRINT_H ++#include ++ ++#include "hilog_cmd.h" ++ ++namespace OHOS { ++namespace HiviewDFX { ++struct LogContent { ++ uint8_t level; ++ uint8_t type; ++ uint32_t pid; ++ uint32_t tid; ++ uint32_t domain; ++ uint32_t tv_sec; ++ uint32_t tv_nsec; ++ uint32_t mono_sec; ++ const char *tag; ++ const char *log; ++}; ++ ++struct LogFormat { ++ bool colorful; ++ FormatTime timeFormat; ++ FormatTimeAccu timeAccuFormat; ++ bool year; ++ bool zone; ++}; ++ ++void LogPrintWithFormat(const LogContent& content, const LogFormat& format, std::ostream& out = std::cout); ++} // namespace HiviewDFX ++} // namespace OHOS ++#endif /* LOG_PRINT_H */ +diff --git a/frameworks/libhilog/utils/include/log_utils.h b/frameworks/libhilog/utils/include/log_utils.h +index 464fe84..6a79155 100644 +--- a/frameworks/libhilog/utils/include/log_utils.h ++++ b/frameworks/libhilog/utils/include/log_utils.h +@@ -1,110 +1,110 @@ +-/* +- * Copyright (c) 2021 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. +- */ +-#ifndef LOG_UTILS_H +-#define LOG_UTILS_H +- +-#include +-#include +-#include +- +-namespace OHOS { +-namespace HiviewDFX { +-template +-class KVMap { +-using ValueCmp = std::function; +-public: +- KVMap(std::unordered_map map, K def_k, V def_v, +- ValueCmp cmp = [](const V& v1, const V& v2) { return v1 == v2; }) +- : str_map(map), def_key(def_k), def_value(def_v), compare(cmp) +- { +- } +- +- const V& GetValue(K key) const +- { +- auto it = str_map.find(key); +- return it == str_map.end() ? def_value : it->second; +- } +- +- const K GetKey(const V& value) const +- { +- for (auto& it : str_map) { +- if (compare(value, it.second)) { +- return it.first; +- } +- } +- return def_key; +- } +- +- std::vector GetAllKeys() const +- { +- std::vector keys; +- for (auto& it : str_map) { +- keys.push_back(it.first); +- } +- return keys; +- } +- +- bool IsValidKey(K key) const +- { +- return (str_map.find(key) != str_map.end()); +- } +- +-private: +- const std::unordered_map str_map; +- const K def_key; +- const V def_value; +- const ValueCmp compare; +-}; +-using StringMap = KVMap; +-std::string ErrorCode2Str(int16_t errorCode); +-std::string LogType2Str(uint16_t logType); +-uint16_t Str2LogType(const std::string& str); +-std::string ComboLogType2Str(uint16_t shiftType); +-uint16_t Str2ComboLogType(const std::string& str); +-std::vector GetAllLogTypes(); +-std::string LogLevel2Str(uint16_t logLevel); +-uint16_t Str2LogLevel(const std::string& str); +-std::string LogLevel2ShortStr(uint16_t logLevel); +-uint16_t ShortStr2LogLevel(const std::string& str); +-uint16_t PrettyStr2LogLevel(const std::string& str); +-std::string ComboLogLevel2Str(uint16_t shiftLevel); +-uint16_t Str2ComboLogLevel(const std::string& str); +-std::string ShowFormat2Str(uint16_t showFormat); +-uint16_t Str2ShowFormat(const std::string& str); +-std::string Size2Str(uint64_t size); +-uint64_t Str2Size(const std::string& str); +- +-constexpr char DEFAULT_SPLIT_DELIMIT[] = ","; +-void Split(const std::string& src, std::vector& dest, +- const std::string& separator = DEFAULT_SPLIT_DELIMIT); +-uint32_t GetBitsCount(uint64_t n); +-uint16_t GetBitPos(uint64_t n); +- +-std::string Uint2DecStr(uint32_t i); +-uint32_t DecStr2Uint(const std::string& str); +-std::string Uint2HexStr(uint32_t i); +-uint32_t HexStr2Uint(const std::string& str); +- +-#if !defined(__WINDOWS__) and !defined(__LINUX__) +-std::string GetProgName(); +-#endif +-std::string GetNameByPid(uint32_t pid); +-uint32_t GetPPidByPid(uint32_t pid); +-uint64_t GenerateHash(const char *p, size_t size); +-void PrintErrorno(int err); +-int WaitingToDo(int max, const std::string& path, std::function func); +-} // namespace HiviewDFX +-} // namespace OHOS +-#endif // LOG_UTILS_H +\ No newline at end of file ++/* ++ * Copyright (c) 2021 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. ++ */ ++#ifndef LOG_UTILS_H ++#define LOG_UTILS_H ++ ++#include ++#include ++#include ++ ++namespace OHOS { ++namespace HiviewDFX { ++template ++class KVMap { ++using ValueCmp = std::function; ++public: ++ KVMap(std::unordered_map map, K def_k, V def_v, ++ ValueCmp cmp = [](const V& v1, const V& v2) { return v1 == v2; }) ++ : str_map(map), def_key(def_k), def_value(def_v), compare(cmp) ++ { ++ } ++ ++ const V& GetValue(K key) const ++ { ++ auto it = str_map.find(key); ++ return it == str_map.end() ? def_value : it->second; ++ } ++ ++ const K GetKey(const V& value) const ++ { ++ for (auto& it : str_map) { ++ if (compare(value, it.second)) { ++ return it.first; ++ } ++ } ++ return def_key; ++ } ++ ++ std::vector GetAllKeys() const ++ { ++ std::vector keys; ++ for (auto& it : str_map) { ++ keys.push_back(it.first); ++ } ++ return keys; ++ } ++ ++ bool IsValidKey(K key) const ++ { ++ return (str_map.find(key) != str_map.end()); ++ } ++ ++private: ++ const std::unordered_map str_map; ++ const K def_key; ++ const V def_value; ++ const ValueCmp compare; ++}; ++using StringMap = KVMap; ++std::string ErrorCode2Str(int16_t errorCode); ++std::string LogType2Str(uint16_t logType); ++uint16_t Str2LogType(const std::string& str); ++std::string ComboLogType2Str(uint16_t shiftType); ++uint16_t Str2ComboLogType(const std::string& str); ++std::vector GetAllLogTypes(); ++std::string LogLevel2Str(uint16_t logLevel); ++uint16_t Str2LogLevel(const std::string& str); ++std::string LogLevel2ShortStr(uint16_t logLevel); ++uint16_t ShortStr2LogLevel(const std::string& str); ++uint16_t PrettyStr2LogLevel(const std::string& str); ++std::string ComboLogLevel2Str(uint16_t shiftLevel); ++uint16_t Str2ComboLogLevel(const std::string& str); ++std::string ShowFormat2Str(uint16_t showFormat); ++uint16_t Str2ShowFormat(const std::string& str); ++std::string Size2Str(uint64_t size); ++uint64_t Str2Size(const std::string& str); ++ ++constexpr char DEFAULT_SPLIT_DELIMIT[] = ","; ++void Split(const std::string& src, std::vector& dest, ++ const std::string& separator = DEFAULT_SPLIT_DELIMIT); ++uint32_t GetBitsCount(uint64_t n); ++uint16_t GetBitPos(uint64_t n); ++ ++std::string Uint2DecStr(uint32_t i); ++uint32_t DecStr2Uint(const std::string& str); ++std::string Uint2HexStr(uint32_t i); ++uint32_t HexStr2Uint(const std::string& str); ++ ++#if !defined(__WINDOWS__) and !defined(__LINUX__) ++std::string GetProgName(); ++#endif ++std::string GetNameByPid(uint32_t pid); ++uint32_t GetPPidByPid(uint32_t pid); ++uint64_t GenerateHash(const char *p, size_t size); ++void PrintErrorno(int err); ++int WaitingToDo(int max, const std::string& path, std::function func); ++} // namespace HiviewDFX ++} // namespace OHOS ++#endif // LOG_UTILS_H +diff --git a/frameworks/libhilog/utils/log_print.cpp b/frameworks/libhilog/utils/log_print.cpp +index 6d47a9a..c7ebf21 100644 +--- a/frameworks/libhilog/utils/log_print.cpp ++++ b/frameworks/libhilog/utils/log_print.cpp +@@ -1,180 +1,180 @@ +-/* +- * Copyright (c) 2022 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. +- */ +-#include +-#include +-#include +-#include +-#include +- +-#include "hilog_common.h" +-#include "log_utils.h" +-#include "log_print.h" +- +-namespace OHOS { +-namespace HiviewDFX { +-using namespace std; +- +-static constexpr int COLOR_BLUE = 75; +-static constexpr int COLOR_DEFAULT = 231; +-static constexpr int COLOR_GREEN = 40; +-static constexpr int COLOR_ORANGE = 166; +-static constexpr int COLOR_RED = 196; +-static constexpr int COLOR_YELLOW = 226; +-static constexpr int TM_YEAR_BASE = 1900; +-static constexpr int DT_WIDTH = 2; +-static constexpr long long NS2US = 1000LL; +-static constexpr long long NS2MS = 1000000LL; +-static constexpr int MONO_WIDTH = 8; +-static constexpr int EPOCH_WIDTH = 10; +-static constexpr int MSEC_WIDTH = 3; +-static constexpr int USEC_WIDTH = 6; +-static constexpr int NSEC_WIDTH = 9; +-static constexpr int PID_WIDTH = 5; +-static constexpr int DOMAIN_WIDTH = 5; +-static constexpr int DOMAIN_SHORT_MASK = 0xFFFFF; +- +-static inline int GetColor(uint16_t level) +-{ +- switch (LogLevel(level)) { +- case LOG_DEBUG: return COLOR_BLUE; +- case LOG_INFO: return COLOR_GREEN; +- case LOG_WARN: return COLOR_ORANGE; +- case LOG_ERROR: return COLOR_RED; +- case LOG_FATAL: return COLOR_YELLOW; +- default: return COLOR_DEFAULT; +- } +-} +- +-static inline const char* GetLogTypePrefix(uint16_t type) +-{ +- switch (LogType(type)) { +- case LOG_APP: return "A"; +- case LOG_INIT: return "I"; +- case LOG_CORE: return "C"; +- case LOG_KMSG: return "K"; +- default: return " "; +- } +-} +- +-static inline uint32_t ShortDomain(uint32_t d) +-{ +- return (d) & DOMAIN_SHORT_MASK; +-} +- +-static void PrintLogPrefix(const LogContent& content, const LogFormat& format, std::ostream& out) +-{ +- // 1. print day & time +- if (format.timeFormat == FormatTime::TIME) { +- struct tm tl; +- time_t time = content.tv_sec; +-#if (defined( __WINDOWS__ )) +- if (localtime_s(&tl, &time) != 0) { +- return; +- } +-#else +- if (localtime_r(&time, &tl) == nullptr) { +- return; +- } +- if (format.zone) { +- out << tl.tm_zone << " "; +- } +-#endif +- if (format.year) { +- out << (tl.tm_year + TM_YEAR_BASE) << "-"; +- } +- out << setfill('0'); +- out << setw(DT_WIDTH) << (tl.tm_mon + 1) << "-" << setw(DT_WIDTH) << tl.tm_mday << " "; +- out << setw(DT_WIDTH) << tl.tm_hour << ":" << setw(DT_WIDTH) << tl.tm_min << ":"; +- out << setw(DT_WIDTH) << tl.tm_sec; +- } else if (format.timeFormat == FormatTime::MONOTONIC) { +- out << setfill(' '); +- out << setw(MONO_WIDTH) << content.mono_sec; +- } else if (format.timeFormat == FormatTime::EPOCH) { +- out << setfill(' '); +- out << setw(EPOCH_WIDTH) << content.tv_sec; +- } else { +- out << "Invalid time format" << endl; +- return; +- } +- // 1.1 print msec/usec/nsec +- out << "."; +- out << setfill('0'); +- if (format.timeAccuFormat == FormatTimeAccu::MSEC) { +- out << setw(MSEC_WIDTH) << (content.tv_nsec / NS2MS); +- } else if (format.timeAccuFormat == FormatTimeAccu::USEC) { +- out << setw(USEC_WIDTH) << (content.tv_nsec / NS2US); +- } else if (format.timeAccuFormat == FormatTimeAccu::NSEC) { +- out << setw(NSEC_WIDTH) << content.tv_nsec; +- } else { +- out << "Invalid time accuracy format" << endl; +- return; +- } +- out << setfill(' '); +- // 2. print pid/tid +- out << " " << setw(PID_WIDTH) << content.pid << " " << setw(PID_WIDTH) << content.tid; +- // 3. print level +- out << " " << LogLevel2ShortStr(content.level) << " "; +- // 4. print log type +- out << GetLogTypePrefix(content.type); +- // 5. print domain +- out << setfill('0'); +- out << hex << setw(DOMAIN_WIDTH) << ShortDomain(content.domain) << dec; +- // 5. print tag & log +- out << "/" << content.tag << ": "; +-} +- +-void LogPrintWithFormat(const LogContent& content, const LogFormat& format, std::ostream& out) +-{ +- // set colorful log +- if (format.colorful) { +- out << "\x1B[38;5;" << GetColor(content.level) << "m"; +- } +- +- const char *pHead = content.log; +- const char *pScan = content.log; +- // split the log content by '\n', and add log prefix(datetime, pid, tid....) to each new line +- while (*pScan != '\0') { +- if (*pScan == '\n') { +- char tmp[MAX_LOG_LEN]; +- int len = static_cast(pScan - pHead); +- errno_t ret = memcpy_s(tmp, MAX_LOG_LEN - 1, pHead, len); +- if (ret != EOK) { +- break; +- } +- tmp[(MAX_LOG_LEN - 1) > len ? len : (MAX_LOG_LEN -1)] = '\0'; +- if (tmp[0] != '\0') { +- PrintLogPrefix(content, format, out); +- out << tmp << endl; +- } +- pHead = pScan + 1; +- } +- pScan++; +- } +- if (pHead[0] != '\0') { +- PrintLogPrefix(content, format, out); +- out << pHead; +- } +- +- // restore color +- if (format.colorful) { +- out << "\x1B[0m"; +- } +- if (pHead[0] != '\0') { +- out << endl; +- } +- return; +-} +-} // namespace HiviewDFX +-} // namespace OHOS +\ No newline at end of file ++/* ++ * Copyright (c) 2022 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include "hilog_common.h" ++#include "log_utils.h" ++#include "log_print.h" ++ ++namespace OHOS { ++namespace HiviewDFX { ++using namespace std; ++ ++static constexpr int COLOR_BLUE = 75; ++static constexpr int COLOR_DEFAULT = 231; ++static constexpr int COLOR_GREEN = 40; ++static constexpr int COLOR_ORANGE = 166; ++static constexpr int COLOR_RED = 196; ++static constexpr int COLOR_YELLOW = 226; ++static constexpr int TM_YEAR_BASE = 1900; ++static constexpr int DT_WIDTH = 2; ++static constexpr long long NS2US = 1000LL; ++static constexpr long long NS2MS = 1000000LL; ++static constexpr int MONO_WIDTH = 8; ++static constexpr int EPOCH_WIDTH = 10; ++static constexpr int MSEC_WIDTH = 3; ++static constexpr int USEC_WIDTH = 6; ++static constexpr int NSEC_WIDTH = 9; ++static constexpr int PID_WIDTH = 5; ++static constexpr int DOMAIN_WIDTH = 5; ++static constexpr int DOMAIN_SHORT_MASK = 0xFFFFF; ++ ++static inline int GetColor(uint16_t level) ++{ ++ switch (LogLevel(level)) { ++ case LOG_DEBUG: return COLOR_BLUE; ++ case LOG_INFO: return COLOR_GREEN; ++ case LOG_WARN: return COLOR_ORANGE; ++ case LOG_ERROR: return COLOR_RED; ++ case LOG_FATAL: return COLOR_YELLOW; ++ default: return COLOR_DEFAULT; ++ } ++} ++ ++static inline const char* GetLogTypePrefix(uint16_t type) ++{ ++ switch (LogType(type)) { ++ case LOG_APP: return "A"; ++ case LOG_INIT: return "I"; ++ case LOG_CORE: return "C"; ++ case LOG_KMSG: return "K"; ++ default: return " "; ++ } ++} ++ ++static inline uint32_t ShortDomain(uint32_t d) ++{ ++ return (d) & DOMAIN_SHORT_MASK; ++} ++ ++static void PrintLogPrefix(const LogContent& content, const LogFormat& format, std::ostream& out) ++{ ++ // 1. print day & time ++ if (format.timeFormat == FormatTime::TIME) { ++ struct tm tl; ++ time_t time = content.tv_sec; ++#if (defined( __WINDOWS__ )) ++ if (localtime_s(&tl, &time) != 0) { ++ return; ++ } ++#else ++ if (localtime_r(&time, &tl) == nullptr) { ++ return; ++ } ++ if (format.zone) { ++ out << tl.tm_zone << " "; ++ } ++#endif ++ if (format.year) { ++ out << (tl.tm_year + TM_YEAR_BASE) << "-"; ++ } ++ out << setfill('0'); ++ out << setw(DT_WIDTH) << (tl.tm_mon + 1) << "-" << setw(DT_WIDTH) << tl.tm_mday << " "; ++ out << setw(DT_WIDTH) << tl.tm_hour << ":" << setw(DT_WIDTH) << tl.tm_min << ":"; ++ out << setw(DT_WIDTH) << tl.tm_sec; ++ } else if (format.timeFormat == FormatTime::MONOTONIC) { ++ out << setfill(' '); ++ out << setw(MONO_WIDTH) << content.mono_sec; ++ } else if (format.timeFormat == FormatTime::EPOCH) { ++ out << setfill(' '); ++ out << setw(EPOCH_WIDTH) << content.tv_sec; ++ } else { ++ out << "Invalid time format" << endl; ++ return; ++ } ++ // 1.1 print msec/usec/nsec ++ out << "."; ++ out << setfill('0'); ++ if (format.timeAccuFormat == FormatTimeAccu::MSEC) { ++ out << setw(MSEC_WIDTH) << (content.tv_nsec / NS2MS); ++ } else if (format.timeAccuFormat == FormatTimeAccu::USEC) { ++ out << setw(USEC_WIDTH) << (content.tv_nsec / NS2US); ++ } else if (format.timeAccuFormat == FormatTimeAccu::NSEC) { ++ out << setw(NSEC_WIDTH) << content.tv_nsec; ++ } else { ++ out << "Invalid time accuracy format" << endl; ++ return; ++ } ++ out << setfill(' '); ++ // 2. print pid/tid ++ out << " " << setw(PID_WIDTH) << content.pid << " " << setw(PID_WIDTH) << content.tid; ++ // 3. print level ++ out << " " << LogLevel2ShortStr(content.level) << " "; ++ // 4. print log type ++ out << GetLogTypePrefix(content.type); ++ // 5. print domain ++ out << setfill('0'); ++ out << hex << setw(DOMAIN_WIDTH) << ShortDomain(content.domain) << dec; ++ // 5. print tag & log ++ out << "/" << content.tag << ": "; ++} ++ ++void LogPrintWithFormat(const LogContent& content, const LogFormat& format, std::ostream& out) ++{ ++ // set colorful log ++ if (format.colorful) { ++ out << "\x1B[38;5;" << GetColor(content.level) << "m"; ++ } ++ ++ const char *pHead = content.log; ++ const char *pScan = content.log; ++ // split the log content by '\n', and add log prefix(datetime, pid, tid....) to each new line ++ while (*pScan != '\0') { ++ if (*pScan == '\n') { ++ char tmp[MAX_LOG_LEN]; ++ int len = static_cast(pScan - pHead); ++ errno_t ret = memcpy_s(tmp, MAX_LOG_LEN - 1, pHead, len); ++ if (ret != EOK) { ++ break; ++ } ++ tmp[(MAX_LOG_LEN - 1) > len ? len : (MAX_LOG_LEN -1)] = '\0'; ++ if (tmp[0] != '\0') { ++ PrintLogPrefix(content, format, out); ++ out << tmp << endl; ++ } ++ pHead = pScan + 1; ++ } ++ pScan++; ++ } ++ if (pHead[0] != '\0') { ++ PrintLogPrefix(content, format, out); ++ out << pHead; ++ } ++ ++ // restore color ++ if (format.colorful) { ++ out << "\x1B[0m"; ++ } ++ if (pHead[0] != '\0') { ++ out << endl; ++ } ++ return; ++} ++} // namespace HiviewDFX ++} // namespace OHOS +diff --git a/frameworks/libhilog/utils/log_utils.cpp b/frameworks/libhilog/utils/log_utils.cpp +index 7cef847..af130c4 100644 +--- a/frameworks/libhilog/utils/log_utils.cpp ++++ b/frameworks/libhilog/utils/log_utils.cpp +@@ -1,522 +1,522 @@ +-/* +- * Copyright (c) 2022 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. +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "hilog_common.h" +-#include "hilog_cmd.h" +-#include "log_utils.h" +- +-namespace { +- constexpr uint32_t ONE_KB = (1UL << 10); +- constexpr uint32_t ONE_MB = (1UL << 20); +- constexpr uint32_t ONE_GB = (1UL << 30); +- constexpr uint64_t ONE_TB = (1ULL << 40); +- constexpr uint32_t DOMAIN_MIN = DOMAIN_APP_MIN; +- constexpr uint32_t DOMAIN_MAX = DOMAIN_OS_MAX; +- constexpr int CMDLINE_PATH_LEN = 32; +- constexpr int CMDLINE_LEN = 128; +- constexpr int STATUS_PATH_LEN = 32; +- constexpr int STATUS_LEN = 1024; +- const std::string SH_NAMES[] = { "sh", "/bin/sh", "/system/bin/sh", "/xbin/sh", "/system/xbin/sh"}; +-} +- +-namespace OHOS { +-namespace HiviewDFX { +-using namespace std; +-using namespace std::chrono; +- +-// Buffer Size&Char Map +-static const KVMap g_SizeMap({ +- {'B', 1}, {'K', ONE_KB}, {'M', ONE_MB}, +- {'G', ONE_GB}, {'T', ONE_TB} +-}, ' ', 0); +- +-string Size2Str(uint64_t size) +-{ +- string str; +- uint64_t unit = 1; +- switch (size) { +- case 0 ... ONE_KB - 1: unit = 1; break; +- case ONE_KB ... ONE_MB - 1: unit = ONE_KB; break; +- case ONE_MB ... ONE_GB - 1: unit = ONE_MB; break; +- case ONE_GB ... ONE_TB - 1: unit = ONE_GB; break; +- default: unit = ONE_TB; break; +- } +- float i = (static_cast(size)) / unit; +- constexpr int len = 16; +- char buf[len] = { 0 }; +- int ret = snprintf_s(buf, len, len - 1, "%.1f", i); +- if (ret <= 0) { +- str = to_string(size); +- } else { +- str = buf; +- } +- return str + g_SizeMap.GetKey(unit); +-} +- +-uint64_t Str2Size(const string& str) +-{ +- std::regex reg("[0-9]+[BKMGT]?"); +- if (!std::regex_match(str, reg)) { +- return 0; +- } +- uint64_t index = str.size() - 1; +- uint64_t unit = g_SizeMap.GetValue(str[index]); +- +- uint64_t value = stoull(str.substr(0, unit !=0 ? index : index + 1)); +- return value * (unit != 0 ? unit : 1); +-} +- +-// Error Codes&Strings Map +-static const KVMap g_ErrorMsgs({ +- {RET_SUCCESS, "Success"}, +- {RET_FAIL, "Unknown failure reason"}, +- {ERR_LOG_LEVEL_INVALID, "Invalid log level, the valid log levels include D/I/W/E/F" +- " or DEBUG/INFO/WARN/ERROR/FATAL"}, +- {ERR_LOG_TYPE_INVALID, "Invalid log type, the valid log types include app/core/init/kmsg"}, +- {ERR_INVALID_RQST_CMD, "Invalid request cmd, please check sourcecode"}, +- {ERR_QUERY_TYPE_INVALID, "Can't query kmsg type logs combined with other types logs."}, +- {ERR_INVALID_DOMAIN_STR, "Invalid domain string"}, +- {ERR_LOG_PERSIST_FILE_SIZE_INVALID, "Invalid log persist file size, file size should be in range [" +- + Size2Str(MIN_LOG_FILE_SIZE) + ", " + Size2Str(MAX_LOG_FILE_SIZE) + "]"}, +- {ERR_LOG_PERSIST_FILE_NAME_INVALID, "Invalid log persist file name, file name should not contain [\\/:*?\"<>|]"}, +- {ERR_LOG_PERSIST_COMPRESS_BUFFER_EXP, "Invalid Log persist compression buffer"}, +- {ERR_LOG_PERSIST_FILE_PATH_INVALID, "Invalid persister file path or persister directory does not exist"}, +- {ERR_LOG_PERSIST_COMPRESS_INIT_FAIL, "Log persist compression initialization failed"}, +- {ERR_LOG_PERSIST_FILE_OPEN_FAIL, "Log persist open file failed"}, +- {ERR_LOG_PERSIST_JOBID_FAIL, "Log persist jobid not exist"}, +- {ERR_LOG_PERSIST_TASK_EXISTED, "Log persist task is existed"}, +- {ERR_DOMAIN_INVALID, ("Invalid domain, domain should be in range (" + Uint2HexStr(DOMAIN_MIN) +- + ", " +Uint2HexStr(DOMAIN_MAX) +"]")}, +- {ERR_MSG_LEN_INVALID, "Invalid message length"}, +- {ERR_LOG_PERSIST_JOBID_INVALID, "Invalid jobid, jobid should be in range [" + to_string(JOB_ID_MIN) +- + ", " + to_string(JOB_ID_MAX) + ")"}, +- {ERR_BUFF_SIZE_INVALID, ("Invalid buffer size, buffer size should be in range [" + Size2Str(MIN_BUFFER_SIZE) +- + ", " + Size2Str(MAX_BUFFER_SIZE) + "]")}, +- {ERR_COMMAND_INVALID, "Mutlti commands can't be used in combination"}, +- {ERR_LOG_FILE_NUM_INVALID, "Invalid number of files"}, +- {ERR_NOT_NUMBER_STR, "Not a numeric string"}, +- {ERR_TOO_MANY_ARGUMENTS, "Too many arguments"}, +- {ERR_DUPLICATE_OPTION, "Too many duplicate options"}, +- {ERR_INVALID_ARGUMENT, "Invalid argument"}, +- {ERR_TOO_MANY_DOMAINS, "Max domain count is " + to_string(MAX_DOMAINS)}, +- {ERR_INVALID_SIZE_STR, "Invalid size string"}, +- {ERR_TOO_MANY_PIDS, "Max pid count is " + to_string(MAX_PIDS)}, +- {ERR_TOO_MANY_TAGS, "Max tag count is " + to_string(MAX_TAGS)}, +- {ERR_TAG_STR_TOO_LONG, ("Tag string too long, max length is " + to_string(MAX_TAG_LEN - 1))}, +- {ERR_REGEX_STR_TOO_LONG, ("Regular expression too long, max length is " + to_string(MAX_REGEX_STR_LEN - 1))}, +- {ERR_FILE_NAME_TOO_LONG, ("File name too long, max length is " + to_string(MAX_FILE_NAME_LEN))}, +- {ERR_SOCKET_CLIENT_INIT_FAIL, "Socket client init failed"}, +- {ERR_SOCKET_WRITE_MSG_HEADER_FAIL, "Socket rite message header failed"}, +- {ERR_SOCKET_WRITE_CMD_FAIL, "Socket write command failed"}, +- {ERR_SOCKET_RECEIVE_RSP, "Unable to receive message from socket"}, +- {ERR_PERSIST_TASK_EMPTY, "No running persist task, please check"}, +- {ERR_JOBID_NOT_EXSIST, "Persist task of this job id doesn't exist, please check"}, +- {ERR_TOO_MANY_JOBS, ("Too many jobs are running, max job count is:" + to_string(MAX_JOBS))}, +- {ERR_STATS_NOT_ENABLE, "Statistic feature is not enable, " +- "please set param persist.sys.hilog.stats true to enable it, " +- "further more, you can set persist.sys.hilog.stats.tag true to enable counting log by tags"}, +- {ERR_NO_RUNNING_TASK, "No running persistent task"}, +- {ERR_NO_PID_PERMISSION, "Permission denied, only shell and root can filter logs by pid"}, +-}, RET_FAIL, "Unknown error code"); +- +-string ErrorCode2Str(int16_t errorCode) +-{ +- return g_ErrorMsgs.GetValue((uint16_t)errorCode) + " [CODE: " + to_string(errorCode) + "]"; +-} +- +-// Log Types&Strings Map +-static const StringMap g_LogTypes({ +- {LOG_INIT, "init"}, {LOG_CORE, "core"}, {LOG_APP, "app"}, {LOG_KMSG, "kmsg"} +-}, LOG_TYPE_MAX, "invalid"); +- +-string LogType2Str(uint16_t logType) +-{ +- return g_LogTypes.GetValue(logType); +-} +- +-uint16_t Str2LogType(const string& str) +-{ +- return g_LogTypes.GetKey(str); +-} +- +-string ComboLogType2Str(uint16_t shiftType) +-{ +- vector types = g_LogTypes.GetAllKeys(); +- string str = ""; +- uint16_t typeAll = 0; +- +- for (uint16_t t : types) { +- typeAll |= (1 << t); +- } +- shiftType &= typeAll; +- for (uint16_t t: types) { +- if ((1 << t) & shiftType) { +- shiftType &= (~(1 << t)); +- str += (LogType2Str(t) + (shiftType != 0 ? "," : "")); +- } +- if (shiftType == 0) { +- break; +- } +- } +- return str; +-} +- +-uint16_t Str2ComboLogType(const string& str) +-{ +- uint16_t logTypes = 0; +- if (str == "") { +- logTypes = (1 << LOG_CORE) | (1 << LOG_APP); +- return logTypes; +- } +- vector vec; +- Split(str, vec); +- for (auto& it : vec) { +- if (it == "") { +- continue; +- } +- uint16_t t = Str2LogType(it); +- if (t == LOG_TYPE_MAX) { +- return 0; +- } +- logTypes |= (1 << t); +- } +- return logTypes; +-} +- +-vector GetAllLogTypes() +-{ +- return g_LogTypes.GetAllKeys(); +-} +- +-// Log Levels&Strings Map +-static const StringMap g_LogLevels({ +- {LOG_DEBUG, "DEBUG"}, {LOG_INFO, "INFO"}, {LOG_WARN, "WARN"}, +- {LOG_ERROR, "ERROR"}, {LOG_FATAL, "FATAL"}, {LOG_LEVEL_MAX, "X"} +-}, LOG_LEVEL_MIN, "INVALID", [](const string& l1, const string& l2) { +- if (l1.length() == l2.length()) { +- return std::equal(l1.begin(), l1.end(), l2.begin(), [](char a, char b) { +- return std::tolower(a) == std::tolower(b); +- }); +- } else { +- return false; +- } +-}); +- +-string LogLevel2Str(uint16_t logLevel) +-{ +- return g_LogLevels.GetValue(logLevel); +-} +- +-uint16_t Str2LogLevel(const string& str) +-{ +- return g_LogLevels.GetKey(str); +-} +- +-// Log Levels&Short Strings Map +-static const StringMap g_ShortLogLevels({ +- {LOG_DEBUG, "D"}, {LOG_INFO, "I"}, {LOG_WARN, "W"}, +- {LOG_ERROR, "E"}, {LOG_FATAL, "F"}, {LOG_LEVEL_MAX, "X"} +-}, LOG_LEVEL_MIN, "V", [](const string& l1, const string& l2) { +- return (l1.length() == 1 && std::tolower(l1[0]) == std::tolower(l2[0])); +-}); +- +-string LogLevel2ShortStr(uint16_t logLevel) +-{ +- return g_ShortLogLevels.GetValue(logLevel); +-} +- +-uint16_t ShortStr2LogLevel(const string& str) +-{ +- return g_ShortLogLevels.GetKey(str); +-} +- +-uint16_t PrettyStr2LogLevel(const string& str) +-{ +- uint16_t level = ShortStr2LogLevel(str); +- if (level == static_cast(LOG_LEVEL_MIN)) { +- return Str2LogLevel(str); +- } +- return level; +-} +- +-string ComboLogLevel2Str(uint16_t shiftLevel) +-{ +- vector levels = g_ShortLogLevels.GetAllKeys(); +- string str = ""; +- uint16_t levelAll = 0; +- +- for (uint16_t l : levels) { +- levelAll |= (1 << l); +- } +- shiftLevel &= levelAll; +- for (uint16_t l: levels) { +- if ((1 << l) & shiftLevel) { +- shiftLevel &= (~(1 << l)); +- str += (LogLevel2Str(l) + (shiftLevel != 0 ? "," : "")); +- } +- if (shiftLevel == 0) { +- break; +- } +- } +- return str; +-} +- +-uint16_t Str2ComboLogLevel(const string& str) +-{ +- uint16_t logLevels = 0; +- if (str == "") { +- logLevels = 0xFFFF; +- return logLevels; +- } +- vector vec; +- Split(str, vec); +- for (auto& it : vec) { +- if (it == "") { +- continue; +- } +- uint16_t t = PrettyStr2LogLevel(it); +- if (t == LOG_LEVEL_MIN || t >= LOG_LEVEL_MAX) { +- return 0; +- } +- logLevels |= (1 << t); +- } +- return logLevels; +-} +- +-void Split(const std::string& src, std::vector& dest, const std::string& separator) +-{ +- std::string str = src; +- std::string substring; +- std::string::size_type start = 0; +- std::string::size_type index; +- dest.clear(); +- index = str.find_first_of(separator, start); +- if (index == std::string::npos) { +- dest.emplace_back(str); +- return; +- } +- do { +- substring = str.substr(start, index - start); +- dest.emplace_back(substring); +- start = index + separator.size(); +- index = str.find(separator, start); +- } while (index != std::string::npos); +- substring = str.substr(start); +- if (substring != "") { +- dest.emplace_back(substring); +- } +-} +- +-uint32_t GetBitsCount(uint64_t n) +-{ +- uint32_t count = 0; +- while (n != 0) { +- ++count; +- n = n & (n-1); +- } +- return count; +-} +- +-uint16_t GetBitPos(uint64_t n) +-{ +- if (!(n && (!(n & (n-1))))) { // only accpet the number which is power of 2 +- return 0; +- } +- +- uint16_t i = 0; +- while (n >> (i++)) {} +- i--; +- return i-1; +-} +- +-enum class Radix { +- RADIX_DEC, +- RADIX_HEX, +-}; +-template +-static string Num2Str(T num, Radix radix) +-{ +- stringstream ss; +- auto r = std::dec; +- if (radix == Radix::RADIX_HEX) { +- r = std::hex; +- } +- ss << r << num; +- return ss.str(); +-} +- +-template +-static void Str2Num(const string& str, T& num, Radix radix) +-{ +- T i = 0; +- std::stringstream ss; +- auto r = std::dec; +- if (radix == Radix::RADIX_HEX) { +- r = std::hex; +- } +- ss << r << str; +- ss >> i; +- num = i; +- return; +-} +- +-string Uint2DecStr(uint32_t i) +-{ +- return Num2Str(i, Radix::RADIX_DEC); +-} +- +-uint32_t DecStr2Uint(const string& str) +-{ +- uint32_t i = 0; +- Str2Num(str, i, Radix::RADIX_DEC); +- return i; +-} +- +-string Uint2HexStr(uint32_t i) +-{ +- return Num2Str(i, Radix::RADIX_HEX); +-} +- +-uint32_t HexStr2Uint(const string& str) +-{ +- uint32_t i = 0; +- Str2Num(str, i, Radix::RADIX_HEX); +- return i; +-} +- +-#if !defined(__WINDOWS__) and !defined(__LINUX__) +-string GetProgName() +-{ +-#ifdef HILOG_USE_MUSL +- return program_invocation_short_name; +-#else +- return getprogname(); +-#endif +-} +-#endif +- +-string GetNameByPid(uint32_t pid) +-{ +- char path[CMDLINE_PATH_LEN] = { 0 }; +- if (snprintf_s(path, CMDLINE_PATH_LEN, CMDLINE_PATH_LEN - 1, "/proc/%d/cmdline", pid) <= 0) { +- return ""; +- } +- char cmdline[CMDLINE_LEN] = { 0 }; +- int i = 0; +- FILE *fp = fopen(path, "r"); +- if (fp == nullptr) { +- return ""; +- } +- while (i < (CMDLINE_LEN - 1)) { +- char c = static_cast(fgetc(fp)); +- // 0. don't need args of cmdline +- // 1. ignore unvisible character +- if (!isgraph(c)) { +- break; +- } +- cmdline[i] = c; +- i++; +- } +- (void)fclose(fp); +- return cmdline; +-} +- +-uint32_t GetPPidByPid(uint32_t pid) +-{ +- uint32_t ppid = 0; +- char path[STATUS_PATH_LEN] = { 0 }; +- if (snprintf_s(path, STATUS_PATH_LEN, STATUS_PATH_LEN - 1, "/proc/%u/status", pid) <= 0) { +- return ppid; +- } +- FILE *fp = fopen(path, "r"); +- if (fp == nullptr) { +- return ppid; +- } +- char buf[STATUS_LEN] = { 0 }; +- size_t ret = fread(buf, sizeof(char), STATUS_LEN - 1, fp); +- (void)fclose(fp); +- if (ret <= 0) { +- return ppid; +- } else { +- buf[ret++] = '\0'; +- } +- char *ppidLoc = strstr(buf, "PPid:"); +- if ((ppidLoc == nullptr) || (sscanf_s(ppidLoc, "PPid:%d", &ppid) == -1)) { +- return ppid; +- } +- std::string ppidName = GetNameByPid(ppid); +- // ppid fork the sh to execute hilog, sh is not wanted ppid +- if (std::find(std::begin(SH_NAMES), std::end(SH_NAMES), ppidName) != std::end(SH_NAMES)) { +- return GetPPidByPid(ppid); +- } +- return ppid; +-} +- +-uint64_t GenerateHash(const char *p, size_t size) +-{ +- static const uint64_t PRIME = 0x100000001B3ull; +- static const uint64_t BASIS = 0xCBF29CE484222325ull; +- uint64_t ret {BASIS}; +- unsigned long i = 0; +- while (i < size) { +- ret ^= *(p + i); +- ret *= PRIME; +- i++; +- } +- return ret; +-} +- +-void PrintErrorno(int err) +-{ +- constexpr int bufSize = 256; +- char buf[bufSize] = { 0 }; +-#ifndef __WINDOWS__ +- (void)strerror_r(err, buf, bufSize); +-#else +- (void)strerror_s(buf, bufSize, err); +-#endif +- std::cerr << "Errno: " << err << ", " << buf << std::endl; +-} +- +-int WaitingToDo(int max, const string& path, function func) +-{ +- chrono::steady_clock::time_point start = chrono::steady_clock::now(); +- chrono::milliseconds wait(max); +- while (true) { +- if (func(path) != RET_FAIL) { +- cout << "waiting for " << path << " successfully!" << endl; +- return RET_SUCCESS; +- } +- +- std::this_thread::sleep_for(10ms); +- if ((chrono::steady_clock::now() - start) > wait) { +- cerr << "waiting for " << path << " failed!" << endl; +- return RET_FAIL; +- } +- } +-} +-} // namespace HiviewDFX +-} // namespace OHOS ++/* ++ * Copyright (c) 2022 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "hilog_common.h" ++#include "hilog_cmd.h" ++#include "log_utils.h" ++ ++namespace { ++ constexpr uint32_t ONE_KB = (1UL << 10); ++ constexpr uint32_t ONE_MB = (1UL << 20); ++ constexpr uint32_t ONE_GB = (1UL << 30); ++ constexpr uint64_t ONE_TB = (1ULL << 40); ++ constexpr uint32_t DOMAIN_MIN = DOMAIN_APP_MIN; ++ constexpr uint32_t DOMAIN_MAX = DOMAIN_OS_MAX; ++ constexpr int CMDLINE_PATH_LEN = 32; ++ constexpr int CMDLINE_LEN = 128; ++ constexpr int STATUS_PATH_LEN = 32; ++ constexpr int STATUS_LEN = 1024; ++ const std::string SH_NAMES[] = { "sh", "/bin/sh", "/system/bin/sh", "/xbin/sh", "/system/xbin/sh"}; ++} ++ ++namespace OHOS { ++namespace HiviewDFX { ++using namespace std; ++using namespace std::chrono; ++ ++// Buffer Size&Char Map ++static const KVMap g_SizeMap({ ++ {'B', 1}, {'K', ONE_KB}, {'M', ONE_MB}, ++ {'G', ONE_GB}, {'T', ONE_TB} ++}, ' ', 0); ++ ++string Size2Str(uint64_t size) ++{ ++ string str; ++ uint64_t unit = 1; ++ switch (size) { ++ case 0 ... ONE_KB - 1: unit = 1; break; ++ case ONE_KB ... ONE_MB - 1: unit = ONE_KB; break; ++ case ONE_MB ... ONE_GB - 1: unit = ONE_MB; break; ++ case ONE_GB ... ONE_TB - 1: unit = ONE_GB; break; ++ default: unit = ONE_TB; break; ++ } ++ float i = (static_cast(size)) / unit; ++ constexpr int len = 16; ++ char buf[len] = { 0 }; ++ int ret = snprintf_s(buf, len, len - 1, "%.1f", i); ++ if (ret <= 0) { ++ str = to_string(size); ++ } else { ++ str = buf; ++ } ++ return str + g_SizeMap.GetKey(unit); ++} ++ ++uint64_t Str2Size(const string& str) ++{ ++ std::regex reg("[0-9]+[BKMGT]?"); ++ if (!std::regex_match(str, reg)) { ++ return 0; ++ } ++ uint64_t index = str.size() - 1; ++ uint64_t unit = g_SizeMap.GetValue(str[index]); ++ ++ uint64_t value = stoull(str.substr(0, unit !=0 ? index : index + 1)); ++ return value * (unit != 0 ? unit : 1); ++} ++ ++// Error Codes&Strings Map ++static const KVMap g_ErrorMsgs({ ++ {RET_SUCCESS, "Success"}, ++ {RET_FAIL, "Unknown failure reason"}, ++ {ERR_LOG_LEVEL_INVALID, "Invalid log level, the valid log levels include D/I/W/E/F" ++ " or DEBUG/INFO/WARN/ERROR/FATAL"}, ++ {ERR_LOG_TYPE_INVALID, "Invalid log type, the valid log types include app/core/init/kmsg"}, ++ {ERR_INVALID_RQST_CMD, "Invalid request cmd, please check sourcecode"}, ++ {ERR_QUERY_TYPE_INVALID, "Can't query kmsg type logs combined with other types logs."}, ++ {ERR_INVALID_DOMAIN_STR, "Invalid domain string"}, ++ {ERR_LOG_PERSIST_FILE_SIZE_INVALID, "Invalid log persist file size, file size should be in range [" ++ + Size2Str(MIN_LOG_FILE_SIZE) + ", " + Size2Str(MAX_LOG_FILE_SIZE) + "]"}, ++ {ERR_LOG_PERSIST_FILE_NAME_INVALID, "Invalid log persist file name, file name should not contain [\\/:*?\"<>|]"}, ++ {ERR_LOG_PERSIST_COMPRESS_BUFFER_EXP, "Invalid Log persist compression buffer"}, ++ {ERR_LOG_PERSIST_FILE_PATH_INVALID, "Invalid persister file path or persister directory does not exist"}, ++ {ERR_LOG_PERSIST_COMPRESS_INIT_FAIL, "Log persist compression initialization failed"}, ++ {ERR_LOG_PERSIST_FILE_OPEN_FAIL, "Log persist open file failed"}, ++ {ERR_LOG_PERSIST_JOBID_FAIL, "Log persist jobid not exist"}, ++ {ERR_LOG_PERSIST_TASK_EXISTED, "Log persist task is existed"}, ++ {ERR_DOMAIN_INVALID, ("Invalid domain, domain should be in range (" + Uint2HexStr(DOMAIN_MIN) ++ + ", " +Uint2HexStr(DOMAIN_MAX) +"]")}, ++ {ERR_MSG_LEN_INVALID, "Invalid message length"}, ++ {ERR_LOG_PERSIST_JOBID_INVALID, "Invalid jobid, jobid should be in range [" + to_string(JOB_ID_MIN) ++ + ", " + to_string(JOB_ID_MAX) + ")"}, ++ {ERR_BUFF_SIZE_INVALID, ("Invalid buffer size, buffer size should be in range [" + Size2Str(MIN_BUFFER_SIZE) ++ + ", " + Size2Str(MAX_BUFFER_SIZE) + "]")}, ++ {ERR_COMMAND_INVALID, "Mutlti commands can't be used in combination"}, ++ {ERR_LOG_FILE_NUM_INVALID, "Invalid number of files"}, ++ {ERR_NOT_NUMBER_STR, "Not a numeric string"}, ++ {ERR_TOO_MANY_ARGUMENTS, "Too many arguments"}, ++ {ERR_DUPLICATE_OPTION, "Too many duplicate options"}, ++ {ERR_INVALID_ARGUMENT, "Invalid argument"}, ++ {ERR_TOO_MANY_DOMAINS, "Max domain count is " + to_string(MAX_DOMAINS)}, ++ {ERR_INVALID_SIZE_STR, "Invalid size string"}, ++ {ERR_TOO_MANY_PIDS, "Max pid count is " + to_string(MAX_PIDS)}, ++ {ERR_TOO_MANY_TAGS, "Max tag count is " + to_string(MAX_TAGS)}, ++ {ERR_TAG_STR_TOO_LONG, ("Tag string too long, max length is " + to_string(MAX_TAG_LEN - 1))}, ++ {ERR_REGEX_STR_TOO_LONG, ("Regular expression too long, max length is " + to_string(MAX_REGEX_STR_LEN - 1))}, ++ {ERR_FILE_NAME_TOO_LONG, ("File name too long, max length is " + to_string(MAX_FILE_NAME_LEN))}, ++ {ERR_SOCKET_CLIENT_INIT_FAIL, "Socket client init failed"}, ++ {ERR_SOCKET_WRITE_MSG_HEADER_FAIL, "Socket rite message header failed"}, ++ {ERR_SOCKET_WRITE_CMD_FAIL, "Socket write command failed"}, ++ {ERR_SOCKET_RECEIVE_RSP, "Unable to receive message from socket"}, ++ {ERR_PERSIST_TASK_EMPTY, "No running persist task, please check"}, ++ {ERR_JOBID_NOT_EXSIST, "Persist task of this job id doesn't exist, please check"}, ++ {ERR_TOO_MANY_JOBS, ("Too many jobs are running, max job count is:" + to_string(MAX_JOBS))}, ++ {ERR_STATS_NOT_ENABLE, "Statistic feature is not enable, " ++ "please set param persist.sys.hilog.stats true to enable it, " ++ "further more, you can set persist.sys.hilog.stats.tag true to enable counting log by tags"}, ++ {ERR_NO_RUNNING_TASK, "No running persistent task"}, ++ {ERR_NO_PID_PERMISSION, "Permission denied, only shell and root can filter logs by pid"}, ++}, RET_FAIL, "Unknown error code"); ++ ++string ErrorCode2Str(int16_t errorCode) ++{ ++ return g_ErrorMsgs.GetValue((uint16_t)errorCode) + " [CODE: " + to_string(errorCode) + "]"; ++} ++ ++// Log Types&Strings Map ++static const StringMap g_LogTypes({ ++ {LOG_INIT, "init"}, {LOG_CORE, "core"}, {LOG_APP, "app"}, {LOG_KMSG, "kmsg"} ++}, LOG_TYPE_MAX, "invalid"); ++ ++string LogType2Str(uint16_t logType) ++{ ++ return g_LogTypes.GetValue(logType); ++} ++ ++uint16_t Str2LogType(const string& str) ++{ ++ return g_LogTypes.GetKey(str); ++} ++ ++string ComboLogType2Str(uint16_t shiftType) ++{ ++ vector types = g_LogTypes.GetAllKeys(); ++ string str = ""; ++ uint16_t typeAll = 0; ++ ++ for (uint16_t t : types) { ++ typeAll |= (1 << t); ++ } ++ shiftType &= typeAll; ++ for (uint16_t t: types) { ++ if ((1 << t) & shiftType) { ++ shiftType &= (~(1 << t)); ++ str += (LogType2Str(t) + (shiftType != 0 ? "," : "")); ++ } ++ if (shiftType == 0) { ++ break; ++ } ++ } ++ return str; ++} ++ ++uint16_t Str2ComboLogType(const string& str) ++{ ++ uint16_t logTypes = 0; ++ if (str == "") { ++ logTypes = (1 << LOG_CORE) | (1 << LOG_APP); ++ return logTypes; ++ } ++ vector vec; ++ Split(str, vec); ++ for (auto& it : vec) { ++ if (it == "") { ++ continue; ++ } ++ uint16_t t = Str2LogType(it); ++ if (t == LOG_TYPE_MAX) { ++ return 0; ++ } ++ logTypes |= (1 << t); ++ } ++ return logTypes; ++} ++ ++vector GetAllLogTypes() ++{ ++ return g_LogTypes.GetAllKeys(); ++} ++ ++// Log Levels&Strings Map ++static const StringMap g_LogLevels({ ++ {LOG_DEBUG, "DEBUG"}, {LOG_INFO, "INFO"}, {LOG_WARN, "WARN"}, ++ {LOG_ERROR, "ERROR"}, {LOG_FATAL, "FATAL"}, {LOG_LEVEL_MAX, "X"} ++}, LOG_LEVEL_MIN, "INVALID", [](const string& l1, const string& l2) { ++ if (l1.length() == l2.length()) { ++ return std::equal(l1.begin(), l1.end(), l2.begin(), [](char a, char b) { ++ return std::tolower(a) == std::tolower(b); ++ }); ++ } else { ++ return false; ++ } ++}); ++ ++string LogLevel2Str(uint16_t logLevel) ++{ ++ return g_LogLevels.GetValue(logLevel); ++} ++ ++uint16_t Str2LogLevel(const string& str) ++{ ++ return g_LogLevels.GetKey(str); ++} ++ ++// Log Levels&Short Strings Map ++static const StringMap g_ShortLogLevels({ ++ {LOG_DEBUG, "D"}, {LOG_INFO, "I"}, {LOG_WARN, "W"}, ++ {LOG_ERROR, "E"}, {LOG_FATAL, "F"}, {LOG_LEVEL_MAX, "X"} ++}, LOG_LEVEL_MIN, "V", [](const string& l1, const string& l2) { ++ return (l1.length() == 1 && std::tolower(l1[0]) == std::tolower(l2[0])); ++}); ++ ++string LogLevel2ShortStr(uint16_t logLevel) ++{ ++ return g_ShortLogLevels.GetValue(logLevel); ++} ++ ++uint16_t ShortStr2LogLevel(const string& str) ++{ ++ return g_ShortLogLevels.GetKey(str); ++} ++ ++uint16_t PrettyStr2LogLevel(const string& str) ++{ ++ uint16_t level = ShortStr2LogLevel(str); ++ if (level == static_cast(LOG_LEVEL_MIN)) { ++ return Str2LogLevel(str); ++ } ++ return level; ++} ++ ++string ComboLogLevel2Str(uint16_t shiftLevel) ++{ ++ vector levels = g_ShortLogLevels.GetAllKeys(); ++ string str = ""; ++ uint16_t levelAll = 0; ++ ++ for (uint16_t l : levels) { ++ levelAll |= (1 << l); ++ } ++ shiftLevel &= levelAll; ++ for (uint16_t l: levels) { ++ if ((1 << l) & shiftLevel) { ++ shiftLevel &= (~(1 << l)); ++ str += (LogLevel2Str(l) + (shiftLevel != 0 ? "," : "")); ++ } ++ if (shiftLevel == 0) { ++ break; ++ } ++ } ++ return str; ++} ++ ++uint16_t Str2ComboLogLevel(const string& str) ++{ ++ uint16_t logLevels = 0; ++ if (str == "") { ++ logLevels = 0xFFFF; ++ return logLevels; ++ } ++ vector vec; ++ Split(str, vec); ++ for (auto& it : vec) { ++ if (it == "") { ++ continue; ++ } ++ uint16_t t = PrettyStr2LogLevel(it); ++ if (t == LOG_LEVEL_MIN || t >= LOG_LEVEL_MAX) { ++ return 0; ++ } ++ logLevels |= (1 << t); ++ } ++ return logLevels; ++} ++ ++void Split(const std::string& src, std::vector& dest, const std::string& separator) ++{ ++ std::string str = src; ++ std::string substring; ++ std::string::size_type start = 0; ++ std::string::size_type index; ++ dest.clear(); ++ index = str.find_first_of(separator, start); ++ if (index == std::string::npos) { ++ dest.emplace_back(str); ++ return; ++ } ++ do { ++ substring = str.substr(start, index - start); ++ dest.emplace_back(substring); ++ start = index + separator.size(); ++ index = str.find(separator, start); ++ } while (index != std::string::npos); ++ substring = str.substr(start); ++ if (substring != "") { ++ dest.emplace_back(substring); ++ } ++} ++ ++uint32_t GetBitsCount(uint64_t n) ++{ ++ uint32_t count = 0; ++ while (n != 0) { ++ ++count; ++ n = n & (n-1); ++ } ++ return count; ++} ++ ++uint16_t GetBitPos(uint64_t n) ++{ ++ if (!(n && (!(n & (n-1))))) { // only accpet the number which is power of 2 ++ return 0; ++ } ++ ++ uint16_t i = 0; ++ while (n >> (i++)) {} ++ i--; ++ return i-1; ++} ++ ++enum class Radix { ++ RADIX_DEC, ++ RADIX_HEX, ++}; ++template ++static string Num2Str(T num, Radix radix) ++{ ++ stringstream ss; ++ auto r = std::dec; ++ if (radix == Radix::RADIX_HEX) { ++ r = std::hex; ++ } ++ ss << r << num; ++ return ss.str(); ++} ++ ++template ++static void Str2Num(const string& str, T& num, Radix radix) ++{ ++ T i = 0; ++ std::stringstream ss; ++ auto r = std::dec; ++ if (radix == Radix::RADIX_HEX) { ++ r = std::hex; ++ } ++ ss << r << str; ++ ss >> i; ++ num = i; ++ return; ++} ++ ++string Uint2DecStr(uint32_t i) ++{ ++ return Num2Str(i, Radix::RADIX_DEC); ++} ++ ++uint32_t DecStr2Uint(const string& str) ++{ ++ uint32_t i = 0; ++ Str2Num(str, i, Radix::RADIX_DEC); ++ return i; ++} ++ ++string Uint2HexStr(uint32_t i) ++{ ++ return Num2Str(i, Radix::RADIX_HEX); ++} ++ ++uint32_t HexStr2Uint(const string& str) ++{ ++ uint32_t i = 0; ++ Str2Num(str, i, Radix::RADIX_HEX); ++ return i; ++} ++ ++#if !defined(__WINDOWS__) and !defined(__LINUX__) ++string GetProgName() ++{ ++#ifdef HILOG_USE_MUSL ++ return program_invocation_short_name; ++#else ++ return getprogname(); ++#endif ++} ++#endif ++ ++string GetNameByPid(uint32_t pid) ++{ ++ char path[CMDLINE_PATH_LEN] = { 0 }; ++ if (snprintf_s(path, CMDLINE_PATH_LEN, CMDLINE_PATH_LEN - 1, "/proc/%d/cmdline", pid) <= 0) { ++ return ""; ++ } ++ char cmdline[CMDLINE_LEN] = { 0 }; ++ int i = 0; ++ FILE *fp = fopen(path, "r"); ++ if (fp == nullptr) { ++ return ""; ++ } ++ while (i < (CMDLINE_LEN - 1)) { ++ char c = static_cast(fgetc(fp)); ++ // 0. don't need args of cmdline ++ // 1. ignore unvisible character ++ if (!isgraph(c)) { ++ break; ++ } ++ cmdline[i] = c; ++ i++; ++ } ++ (void)fclose(fp); ++ return cmdline; ++} ++ ++uint32_t GetPPidByPid(uint32_t pid) ++{ ++ uint32_t ppid = 0; ++ char path[STATUS_PATH_LEN] = { 0 }; ++ if (snprintf_s(path, STATUS_PATH_LEN, STATUS_PATH_LEN - 1, "/proc/%u/status", pid) <= 0) { ++ return ppid; ++ } ++ FILE *fp = fopen(path, "r"); ++ if (fp == nullptr) { ++ return ppid; ++ } ++ char buf[STATUS_LEN] = { 0 }; ++ size_t ret = fread(buf, sizeof(char), STATUS_LEN - 1, fp); ++ (void)fclose(fp); ++ if (ret <= 0) { ++ return ppid; ++ } else { ++ buf[ret++] = '\0'; ++ } ++ char *ppidLoc = strstr(buf, "PPid:"); ++ if ((ppidLoc == nullptr) || (sscanf_s(ppidLoc, "PPid:%d", &ppid) == -1)) { ++ return ppid; ++ } ++ std::string ppidName = GetNameByPid(ppid); ++ // ppid fork the sh to execute hilog, sh is not wanted ppid ++ if (std::find(std::begin(SH_NAMES), std::end(SH_NAMES), ppidName) != std::end(SH_NAMES)) { ++ return GetPPidByPid(ppid); ++ } ++ return ppid; ++} ++ ++uint64_t GenerateHash(const char *p, size_t size) ++{ ++ static const uint64_t PRIME = 0x100000001B3ull; ++ static const uint64_t BASIS = 0xCBF29CE484222325ull; ++ uint64_t ret {BASIS}; ++ unsigned long i = 0; ++ while (i < size) { ++ ret ^= *(p + i); ++ ret *= PRIME; ++ i++; ++ } ++ return ret; ++} ++ ++void PrintErrorno(int err) ++{ ++ constexpr int bufSize = 256; ++ char buf[bufSize] = { 0 }; ++#ifndef __WINDOWS__ ++ (void)strerror_r(err, buf, bufSize); ++#else ++ (void)strerror_s(buf, bufSize, err); ++#endif ++ std::cerr << "Errno: " << err << ", " << buf << std::endl; ++} ++ ++int WaitingToDo(int max, const string& path, function func) ++{ ++ chrono::steady_clock::time_point start = chrono::steady_clock::now(); ++ chrono::milliseconds wait(max); ++ while (true) { ++ if (func(path) != RET_FAIL) { ++ cout << "waiting for " << path << " successfully!" << endl; ++ return RET_SUCCESS; ++ } ++ ++ std::this_thread::sleep_for(10ms); ++ if ((chrono::steady_clock::now() - start) > wait) { ++ cerr << "waiting for " << path << " failed!" << endl; ++ return RET_FAIL; ++ } ++ } ++} ++} // namespace HiviewDFX ++} // namespace OHOS +diff --git a/frameworks/libhilog/vsnprintf/include/output_p.inl b/frameworks/libhilog/vsnprintf/include/output_p.inl +new file mode 100644 +index 0000000..d58873b +--- /dev/null ++++ b/frameworks/libhilog/vsnprintf/include/output_p.inl +@@ -0,0 +1,1294 @@ ++/* ++ * Copyright (c) 2021 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. ++ */ ++ ++ ++/* [Standardize-exceptions] Use unsafe function: Portability ++ * [reason] Use unsafe function to implement security function to maintain platform compatibility. ++ * And sufficient input validation is performed before calling ++ */ ++ ++#ifndef OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 ++#define OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 ++ ++#define SECUREC_FLOAT_BUFSIZE (309+40) /* max float point value */ ++#define SECUREC_FLOAT_BUFSIZE_LB (4932+40) /* max long double value */ ++ ++#define SECUREC_INT_MAX 2147483647 ++ ++#define SECUREC_MUL10(x) ((((x) << 2) + (x)) << 1) ++#define SECUREC_INT_MAX_DIV_TEN 21474836 ++#define SECUREC_MUL10_ADD_BEYOND_MAX(val) (((val) > SECUREC_INT_MAX_DIV_TEN)) ++ ++#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K ++#define SECUREC_FMT_STR_LEN (8) ++#else ++#define SECUREC_FMT_STR_LEN (16) ++#endif ++ ++typedef struct { ++ unsigned int flags; ++ int fldWidth; ++ int precision; ++ int bufferIsWide; /* flag for buffer contains wide chars */ ++ int dynWidth; /* %* 1 width from variable parameter ;0 not */ ++ int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */ ++} SecFormatAttr; ++ ++typedef union { ++ char *str; /* not a null terminated string */ ++ wchar_t *wStr; ++} SecFormatBuf; ++ ++typedef union { ++ char str[SECUREC_BUFFER_SIZE + 1]; ++#ifdef SECUREC_FOR_WCHAR ++ wchar_t wStr[SECUREC_BUFFER_SIZE + 1]; ++#endif ++} SecBuffer; ++ ++static int SecIndirectSprintf(char *strDest, const char *format, ...) ++{ ++ int ret; /* If initialization causes e838 */ ++ va_list arglist; ++ ++ va_start(arglist, format); ++ SECUREC_MASK_MSVC_CRT_WARNING ++ ret = vsprintf(strDest, format, arglist); ++ SECUREC_END_MASK_MSVC_CRT_WARNING ++ va_end(arglist); ++ (void)arglist; /* to clear e438 last value assigned not used , the compiler will optimize this code */ ++ ++ return ret; ++} ++ ++#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT ++/* to clear e506 warning */ ++static int SecIsSameSize(size_t sizeA, size_t sizeB) ++{ ++ return sizeA == sizeB; ++} ++#endif ++ ++#define SECUREC_SPECIAL(_val, Base) \ ++ case Base: \ ++ do { \ ++ *--formatBuf.str = digits[_val % Base]; \ ++ }while ((_val /= Base) != 0) ++ ++#define SECUREC_SAFE_WRITE_PREFIX(src, txtLen, _stream, outChars) do { \ ++ for (ii = 0; ii < txtLen; ++ii) { \ ++ *((SecChar *)(void *)(_stream->cur)) = *(src); \ ++ _stream->cur += sizeof(SecChar); \ ++ ++(src); \ ++ } \ ++ _stream->count -= txtLen * (int)(sizeof(SecChar)); \ ++ *(outChars) = *(outChars) + (txtLen); \ ++ } SECUREC_WHILE_ZERO ++ ++#define SECUREC_SAFE_WRITE_STR(src, txtLen, _stream, outChars) do { \ ++ if (txtLen < 12 /* for mobile number length */) { \ ++ for (ii = 0; ii < txtLen; ++ii) { \ ++ *((SecChar *)(void *)(_stream->cur)) = *(src); \ ++ _stream->cur += sizeof(SecChar); \ ++ ++(src); \ ++ } \ ++ } else { \ ++ (void)memcpy(_stream->cur, src, ((size_t)(unsigned int)txtLen * (sizeof(SecChar)))); \ ++ _stream->cur += (size_t)(unsigned int)txtLen * (sizeof(SecChar)); \ ++ } \ ++ _stream->count -= txtLen * (int)(sizeof(SecChar)); \ ++ *(outChars) = *(outChars) + (txtLen); \ ++ } SECUREC_WHILE_ZERO ++ ++#define SECUREC_SAFE_WRITE_CHAR(_ch, _stream, outChars) do { \ ++ *((SecChar *)(void *)(_stream->cur)) = (SecChar)_ch; \ ++ _stream->cur += sizeof(SecChar); \ ++ _stream->count -= (int)(sizeof(SecChar)); \ ++ *(outChars) = *(outChars) + 1; \ ++ } SECUREC_WHILE_ZERO ++ ++#define SECUREC_SAFE_PADDING(padChar, padLen, _stream, outChars) do { \ ++ for (ii = 0; ii < padLen; ++ii) { \ ++ *((SecChar *)(void *)(_stream->cur)) = (SecChar)padChar; \ ++ _stream->cur += sizeof(SecChar); \ ++ } \ ++ _stream->count -= padLen * (int)(sizeof(SecChar)); \ ++ *(outChars) = *(outChars) + (padLen); \ ++ } SECUREC_WHILE_ZERO ++ ++/* The count variable can be reduced to 0, and the external function complements the \0 terminator. */ ++#define SECUREC_IS_REST_BUF_ENOUGH(needLen) ((int)(stream->count - (int)needLen * (int)(sizeof(SecChar))) >= 0) ++ ++#define SECUREC_FMT_STATE_OFFSET 256 ++#ifdef SECUREC_FOR_WCHAR ++#define SECUREC_FMT_TYPE(c, fmtTable) ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? \ ++ (fmtTable[(unsigned char)(c)]) : 0) ++#define SECUREC_DECODE_STATE(c, fmtTable, laststate) (SecFmtState)(((fmtTable[(SECUREC_FMT_TYPE(c,fmtTable)) * \ ++ ((unsigned char)STAT_INVALID + 1) + \ ++ (unsigned char)(laststate) + \ ++ SECUREC_FMT_STATE_OFFSET]))) ++#else ++#define SECUREC_DECODE_STATE(c,fmtTable,laststate) (SecFmtState)((fmtTable[(fmtTable[(unsigned char)(c)]) * \ ++ ((unsigned char)STAT_INVALID + 1) + \ ++ (unsigned char)(laststate) + \ ++ SECUREC_FMT_STATE_OFFSET])) ++#endif ++ ++#define PUBLIC_FLAG_LEN 8 ++#define PRIVATE_FLAG_LEN 9 ++#define PUBLIC_FLAG "{public}" ++#define PRIVATE_FLAG "{private}" ++ ++static void SecWritePrivateStr(SecPrintfStream *stream, int *pCharsOut) ++{ ++ int ii = 0; ++#define PRIVATE_STR_LEN (9) ++#ifndef SECUREC_FOR_WCHAR ++ static const char privacyString[] = ""; ++ const char *pPrivStr = privacyString; ++ ++ if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) { ++ SECUREC_SAFE_WRITE_STR(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); ++ } else { ++ SECUREC_WRITE_STRING(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); ++ } ++#else ++ static const wchar_t wprivacyString[] = { L'<', L'p', L'r', L'i', L'v', L'a', L't', L'e', L'>', L'\0' }; ++ const wchar_t *pwPrivStr = wprivacyString; ++ ++ if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) { ++ SECUREC_SAFE_WRITE_STR(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); ++ } else { ++ SECUREC_WRITE_STRING(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); ++ } ++#endif ++} ++ ++static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) ++{ ++ switch (ch) { ++ case SECUREC_CHAR(' '): ++ attr->flags |= SECUREC_FLAG_SIGN_SPACE; ++ break; ++ case SECUREC_CHAR('+'): ++ attr->flags |= SECUREC_FLAG_SIGN; ++ break; ++ case SECUREC_CHAR('-'): ++ attr->flags |= SECUREC_FLAG_LEFT; ++ break; ++ case SECUREC_CHAR('0'): ++ attr->flags |= SECUREC_FLAG_LEADZERO; /* add zero th the front */ ++ break; ++ case SECUREC_CHAR('#'): ++ attr->flags |= SECUREC_FLAG_ALTERNATE; /* output %x with 0x */ ++ break; ++ default: ++ break; ++ } ++ return; ++} ++ ++static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format) ++{ ++ switch (ch) { ++#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT ++ case SECUREC_CHAR('j'): ++ attr->flags |= SECUREC_FLAG_INTMAX; ++ break; ++#endif ++ case SECUREC_CHAR('q'): [[fallthrough]]; ++ case SECUREC_CHAR('L'): ++ attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE; ++ break; ++ case SECUREC_CHAR('l'): ++ if (**format == SECUREC_CHAR('l')) { ++ ++(*format); ++ attr->flags |= SECUREC_FLAG_LONGLONG; /* long long */ ++ } else { ++ attr->flags |= SECUREC_FLAG_LONG; /* long int or wchar_t */ ++ } ++ break; ++ case SECUREC_CHAR('t'): ++ attr->flags |= SECUREC_FLAG_PTRDIFF; ++ break; ++#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT ++ case SECUREC_CHAR('z'): ++ attr->flags |= SECUREC_FLAG_SIZE; ++ break; ++ case SECUREC_CHAR('Z'): ++ attr->flags |= SECUREC_FLAG_SIZE; ++ break; ++#endif ++ ++ case SECUREC_CHAR('I'): ++#ifdef SECUREC_ON_64BITS ++ attr->flags |= SECUREC_FLAG_I64; /* %I to INT64 */ ++#endif ++ if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) { ++ (*format) += 2; ++ attr->flags |= SECUREC_FLAG_I64; /* %I64 to INT64 */ ++ } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) { ++ (*format) += 2; ++ attr->flags &= ~SECUREC_FLAG_I64; /* %I64 to INT32 */ ++ } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) || ++ (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) || ++ (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) { ++ /* do nothing */ ++ } else { ++ /* Compatibility code for "%I" just print I */ ++ return -1; ++ } ++ break; ++ ++ case SECUREC_CHAR('h'): ++ if (**format == SECUREC_CHAR('h')) ++ attr->flags |= SECUREC_FLAG_CHAR; /* char */ ++ else ++ attr->flags |= SECUREC_FLAG_SHORT; /* short int */ ++ break; ++ ++ case SECUREC_CHAR('w'): ++ attr->flags |= SECUREC_FLAG_WIDECHAR; /* wide char */ ++ break; ++ default: ++ break; ++ ++ } ++ ++ return 0; ++} ++ ++static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer) ++{ ++ int textLen; ++ wchar_t wchar; ++ ++#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS)) ++ attr->flags &= ~SECUREC_FLAG_LEADZERO; ++#endif ++ ++#ifdef SECUREC_FOR_WCHAR ++ attr->bufferIsWide = 1; ++ wchar = (wchar_t)cValue; ++ if (attr->flags & SECUREC_FLAG_SHORT) { ++ /* multibyte character to wide character */ ++ char tempchar[2]; ++ tempchar[0] = (char)(wchar & 0x00ff); ++ tempchar[1] = '\0'; ++ ++ if (mbtowc(buffer->wStr, tempchar, sizeof(tempchar)) < 0) { ++ return -1; ++ } ++ } else { ++ buffer->wStr[0] = wchar; ++ } ++ formatBuf->wStr = buffer->wStr; ++ textLen = 1; /* only 1 wide character */ ++#else ++ attr->bufferIsWide = 0; ++ if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { ++ wchar = (wchar_t)cValue; ++ /* wide character to multibyte character */ ++ SECUREC_MASK_MSVC_CRT_WARNING ++ textLen = wctomb(buffer->str, wchar); ++ SECUREC_END_MASK_MSVC_CRT_WARNING ++ if (textLen < 0) { ++ return -1; ++ } ++ } else { ++ /* get multibyte character from argument */ ++ unsigned short temp; ++ temp = (unsigned short)cValue; ++ buffer->str[0] = (char)temp; ++ textLen = 1; ++ } ++ formatBuf->str = buffer->str; ++#endif ++ ++ return textLen; ++} ++ ++static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf) ++{ ++ /* literal string to print null ptr, define it on stack rather than const text area ++ is to avoid gcc warning with pointing const text with variable */ ++ static char strNullString[8] = "(null)"; ++ static wchar_t wStrNullString[8] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' }; ++ ++ int finalPrecision; ++ char *strEnd = NULL; ++ wchar_t *wStrEnd = NULL; ++ int textLen; ++ ++#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX)) ++ attr->flags &= ~SECUREC_FLAG_LEADZERO; ++#endif ++ finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision; ++ formatBuf->str = argPtr; ++ ++#ifdef SECUREC_FOR_WCHAR ++#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) ++ if (!(attr->flags & SECUREC_FLAG_LONG)) { ++ attr->flags |= SECUREC_FLAG_SHORT; ++ } ++#endif ++ if (attr->flags & SECUREC_FLAG_SHORT) { ++ if (formatBuf->str == NULL) { /* NULL passed, use special string */ ++ formatBuf->str = strNullString; ++ } ++ strEnd = formatBuf->str; ++ for (textLen = 0; textLen < finalPrecision && *strEnd; textLen++) { ++ ++strEnd; ++ } ++ /* textLen now contains length in multibyte chars */ ++ } else { ++ if (formatBuf->wStr == NULL) { /* NULL passed, use special string */ ++ formatBuf->wStr = wStrNullString; ++ } ++ attr->bufferIsWide = 1; ++ wStrEnd = formatBuf->wStr; ++ while (finalPrecision-- && *wStrEnd) { ++ ++wStrEnd; ++ } ++ textLen = (int)(wStrEnd - formatBuf->wStr); /* in wchar_ts */ ++ /* textLen now contains length in wide chars */ ++ } ++#else /* SECUREC_FOR_WCHAR */ ++ if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { ++ if (formatBuf->wStr == NULL) { /* NULL passed, use special string */ ++ formatBuf->wStr = wStrNullString; ++ } ++ attr->bufferIsWide = 1; ++ wStrEnd = formatBuf->wStr; ++ while (finalPrecision-- && *wStrEnd) { ++ ++wStrEnd; ++ } ++ textLen = (int)(wStrEnd - formatBuf->wStr); ++ } else { ++ if (formatBuf->str == NULL) { /* meet NULL, use special string */ ++ formatBuf->str = strNullString; ++ } ++ ++ if (finalPrecision == SECUREC_INT_MAX) { ++ /* precision NOT assigned */ ++ /* The strlen performance is high when the string length is greater than 32 */ ++ textLen = (int)strlen(formatBuf->str); ++ } else { ++ /* precision assigned */ ++ strEnd = formatBuf->str; ++ while (finalPrecision-- && *strEnd) { ++ ++strEnd; ++ } ++ textLen = (int)(strEnd - formatBuf->str); /* length of the string */ ++ } ++ ++ } ++ ++#endif /* SECUREC_FOR_WCHAR */ ++ return textLen; ++} ++ ++HILOG_LOCAL_API ++int SecOutputPS(SecPrintfStream *stream, int priv, const char *cformat, va_list arglist) ++{ ++ const SecChar *format = cformat; ++ ++ char *floatBuf = NULL; ++ SecFormatBuf formatBuf; ++ static const char *itoaUpperDigits = "0123456789ABCDEFX"; ++ static const char *itoaLowerDigits = "0123456789abcdefx"; ++ const char *digits = itoaUpperDigits; ++ int ii = 0; ++ ++ unsigned int radix; ++ int charsOut; /* characters written */ ++ ++ int prefixLen = 0; ++ int padding = 0; ++ ++ int textLen; /* length of the text */ ++ int bufferSize = 0; /* size of formatBuf.str */ ++ int noOutput = 0; ++ ++ SecFmtState state; ++ SecFmtState laststate; ++ ++ SecChar prefix[2] = { 0 }; ++ SecChar ch; /* currently read character */ ++ ++ static const unsigned char fmtCharTable[337] = { ++ /* type 0: nospecial meaning; ++ 1: '%'; ++ 2: '.' ++ 3: '*' ++ 4: '0' ++ 5: '1' ... '9' ++ 6: ' ', '+', '-', '#' ++ 7: 'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j' ++ 8: 'd','o','u','i','x','X','e','f','g' ++ */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00, ++ 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08, ++ 0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, ++ /* fill zero for normal char 128 byte for 0x80 - 0xff */ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ /* state 0: normal ++ 1: percent ++ 2: flag ++ 3: width ++ 4: dot ++ 5: precis ++ 6: size ++ 7: type ++ 8: invalid ++ */ ++ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, ++ 0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05, ++ 0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, ++ 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, ++ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, ++ 0x00 ++ }; ++ ++ SecFormatAttr formatAttr; ++ SecBuffer buffer; ++ formatAttr.flags = 0; ++ formatAttr.bufferIsWide = 0; /* flag for buffer contains wide chars */ ++ formatAttr.fldWidth = 0; ++ formatAttr.precision = 0; ++ formatAttr.dynWidth = 0; ++ formatAttr.dynPrecision = 0; ++ ++ charsOut = 0; ++ textLen = 0; ++ state = STAT_NORMAL; /* starting state */ ++ formatBuf.str = NULL; ++ ++ int isPrivacy = 1; /*whether show private string*/ ++ ++ /* loop each format character */ ++ /* remove format != NULL */ ++ while ((ch = *format++) != SECUREC_CHAR('\0') && charsOut >= 0) { ++ laststate = state; ++ state = SECUREC_DECODE_STATE(ch, fmtCharTable, laststate); ++ ++ switch (state) { ++ case STAT_NORMAL: ++ ++NORMAL_CHAR: ++ ++ /* normal state, write character */ ++ if (SECUREC_IS_REST_BUF_ENOUGH(1 /* only one char */ )) { ++ SECUREC_SAFE_WRITE_CHAR(ch, stream, &charsOut); /* char * cast to wchar * */ ++ } else { ++#ifdef SECUREC_FOR_WCHAR ++ SECUREC_WRITE_CHAR(ch, stream, &charsOut); ++#else ++ /* optimize function call to code */ ++ charsOut = -1; ++ stream->count = -1; ++#endif ++ } ++ ++ continue; ++ ++ case STAT_PERCENT: ++ /* set default values */ ++ prefixLen = 0; ++ noOutput = 0; ++ formatAttr.flags = 0; ++ formatAttr.fldWidth = 0; ++ formatAttr.precision = -1; ++ formatAttr.bufferIsWide = 0; ++ if (*format == SECUREC_CHAR('{')) { ++ if (strncmp(format, PUBLIC_FLAG, PUBLIC_FLAG_LEN) == 0) { ++ isPrivacy = 0; ++ format += PUBLIC_FLAG_LEN; ++ } ++ else if (strncmp(format, PRIVATE_FLAG, PRIVATE_FLAG_LEN) == 0) { ++ isPrivacy = 1; ++ format += PRIVATE_FLAG_LEN; ++ } ++ } ++ else { ++ isPrivacy = 1; ++ } ++ ++ if (0 == priv) { ++ isPrivacy = 0; ++ } ++ ++ break; ++ ++ case STAT_FLAG: ++ /* set flag based on which flag character */ ++ SecDecodeFlags(ch, &formatAttr); ++ break; ++ ++ case STAT_WIDTH: ++ /* update width value */ ++ if (ch == SECUREC_CHAR('*')) { ++ /* get width */ ++ formatAttr.fldWidth = (int)va_arg(arglist, int); ++ if (formatAttr.fldWidth < 0) { ++ formatAttr.flags |= SECUREC_FLAG_LEFT; ++ formatAttr.fldWidth = -formatAttr.fldWidth; ++ } ++ formatAttr.dynWidth = 1; ++ } else { ++ if (laststate != STAT_WIDTH) { ++ formatAttr.fldWidth = 0; ++ } ++ if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.fldWidth)) { ++ return -1; ++ } ++ formatAttr.fldWidth = (int)SECUREC_MUL10((unsigned int)formatAttr.fldWidth) + (ch - SECUREC_CHAR('0')); ++ formatAttr.dynWidth = 0; ++ } ++ break; ++ ++ case STAT_DOT: ++ formatAttr.precision = 0; ++ break; ++ ++ case STAT_PRECIS: ++ /* update precision value */ ++ if (ch == SECUREC_CHAR('*')) { ++ /* get precision from arg list */ ++ formatAttr.precision = (int)va_arg(arglist, int); ++ if (formatAttr.precision < 0) { ++ formatAttr.precision = -1; ++ } ++ formatAttr.dynPrecision = 1; ++ } else { ++ /* add digit to current precision */ ++ if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.precision)) { ++ return -1; ++ } ++ formatAttr.precision = ++ (int)SECUREC_MUL10((unsigned int)formatAttr.precision) + (ch - SECUREC_CHAR('0')); ++ formatAttr.dynPrecision = 0; ++ } ++ break; ++ ++ case STAT_SIZE: ++ /* read a size specifier, set the formatAttr.flags based on it */ ++ if (SecDecodeSize(ch, &formatAttr, &format) != 0) { ++ /* Compatibility code for "%I" just print I */ ++ state = STAT_NORMAL; ++ goto NORMAL_CHAR; ++ } ++ break; ++ ++ case STAT_TYPE: ++ ++ switch (ch) { ++ ++ case SECUREC_CHAR('C'): ++ /* wide char */ ++ if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { ++ ++#ifdef SECUREC_FOR_WCHAR ++ formatAttr.flags |= SECUREC_FLAG_SHORT; ++#else ++ formatAttr.flags |= SECUREC_FLAG_WIDECHAR; ++#endif ++ } ++ [[fallthrough]]; ++ case SECUREC_CHAR('c'): ++ { ++ unsigned int cValue = (unsigned int)va_arg(arglist, int); ++ /*if it's a private arg, just write to stream*/ ++ if (isPrivacy == 1) { ++ break; ++ } ++ textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer); ++ if (textLen < 0) { ++ noOutput = 1; ++ } ++ } ++ break; ++ case SECUREC_CHAR('S'): /* wide char string */ ++#ifndef SECUREC_FOR_WCHAR ++ if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { ++ formatAttr.flags |= SECUREC_FLAG_WIDECHAR; ++ } ++#else ++ if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { ++ formatAttr.flags |= SECUREC_FLAG_SHORT; ++ } ++#endif ++ [[fallthrough]]; ++ case SECUREC_CHAR('s'): ++ { ++ char *argPtr = (char *)va_arg(arglist, char *); ++ /*if it's a private arg, just write to stream*/ ++ if (isPrivacy == 1) { ++ break; ++ } ++ textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf); ++ } ++ break; ++ ++ case SECUREC_CHAR('n'): ++ /* higher risk disable it */ ++ return -1; ++ ++ case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */ ++ case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ ++ case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */ ++ case SECUREC_CHAR('A'): /* fall-through */ /* FALLTHRU */ ++ /* convert format char to lower , use Explicit conversion to clean up compilation warning */ ++ ch = (SecChar)(ch + ((SecChar)(SECUREC_CHAR('a')) - (SECUREC_CHAR('A')))); ++ [[fallthrough]]; ++ case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */ ++ case SECUREC_CHAR('f'): /* fall-through */ /* FALLTHRU */ ++ case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */ ++ case SECUREC_CHAR('a'): ++ { ++ /*if it's a private arg, just write to stream*/ ++ if (isPrivacy == 1) { ++#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT ++ if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { ++ (void)va_arg(arglist, long double); ++ } else ++#endif ++ { ++ (void)va_arg(arglist, double); ++ } ++ break; ++ } ++ ++ /* floating point conversion */ ++ formatBuf.str = buffer.str; /* output buffer for float string with default size */ ++ ++ /* compute the precision value */ ++ if (formatAttr.precision < 0) { ++ formatAttr.precision = 6; ++ } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) { ++ formatAttr.precision = 1; ++ } ++ ++ /* calc buffer size to store long double value */ ++ if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { ++ if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE_LB)) { ++ noOutput = 1; ++ break; ++ } ++ bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision; ++ } else { ++ if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE)) { ++ noOutput = 1; ++ break; ++ } ++ bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision; ++ } ++ if (formatAttr.fldWidth > bufferSize) { ++ bufferSize = formatAttr.fldWidth; ++ } ++ ++ if (bufferSize >= SECUREC_BUFFER_SIZE) { ++ /* the current value of SECUREC_BUFFER_SIZE could NOT store the formatted float string */ ++ /* size include '+' and '\0' */ ++ floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize + (size_t)2)); ++ if (floatBuf != NULL) { ++ formatBuf.str = floatBuf; ++ } else { ++ noOutput = 1; ++ break; ++ } ++ } ++ ++ { ++ /* add following code to call system sprintf API for float number */ ++ const SecChar *pFltFmt = format - 2; /* point to the position before 'f' or 'g' */ ++ int k; ++ int fltFmtStrLen; ++ char fltFmtBuf[SECUREC_FMT_STR_LEN]; ++ char *fltFmtStr = fltFmtBuf; ++ char *fltFmtHeap = NULL; /* to clear warning */ ++ ++ /* must meet '%' (normal format) or '}'(with{private} or{public} format)*/ ++ while (SECUREC_CHAR('%') != *pFltFmt && SECUREC_CHAR('}') != *pFltFmt) { ++ --pFltFmt; ++ } ++ fltFmtStrLen = (int)((format - pFltFmt) + 1); /* with ending terminator */ ++ if (fltFmtStrLen > SECUREC_FMT_STR_LEN) { ++ /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */ ++ fltFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fltFmtStrLen)); ++ if (fltFmtHeap == NULL) { ++ noOutput = 1; ++ break; ++ } else { ++ fltFmtHeap[0] = '%'; ++ for (k = 1; k < fltFmtStrLen - 1; ++k) { ++ /* convert wchar to char */ ++ fltFmtHeap[k] = (char)(pFltFmt[k]); /* copy the format string */ ++ } ++ fltFmtHeap[k] = '\0'; ++ ++ fltFmtStr = fltFmtHeap; ++ } ++ } else { ++ /* purpose of the repeat code is to solve the tool alarm Redundant_Null_Check */ ++ fltFmtBuf[0] = '%'; ++ for (k = 1; k < fltFmtStrLen - 1; ++k) { ++ /* convert wchar to char */ ++ fltFmtBuf[k] = (char)(pFltFmt[k]); /* copy the format string */ ++ } ++ fltFmtBuf[k] = '\0'; ++ } ++ ++#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT ++ if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { ++ long double tmp = (long double)va_arg(arglist, long double); ++ /* call system sprintf to format float value */ ++ if (formatAttr.dynWidth && formatAttr.dynPrecision) { ++ textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, ++ formatAttr.fldWidth,formatAttr.precision, tmp); ++ } else if (formatAttr.dynWidth) { ++ textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, ++ formatAttr.fldWidth, tmp); ++ } else if (formatAttr.dynPrecision) { ++ textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, ++ formatAttr.precision, tmp); ++ } else { ++ textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp); ++ } ++ } else ++#endif ++ { ++ double tmp = (double)va_arg(arglist, double); ++ if (formatAttr.dynWidth && formatAttr.dynPrecision) { ++ textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth, ++ formatAttr.precision, tmp); ++ } else if (formatAttr.dynWidth) { ++ textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth, ++ tmp); ++ } else if (formatAttr.dynPrecision) { ++ textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.precision, ++ tmp); ++ } else { ++ textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp); ++ } ++ } ++ ++ if (fltFmtHeap != NULL) { ++ /* if buffer is allocated on heap, free it */ ++ SECUREC_FREE(fltFmtHeap); ++ fltFmtHeap = NULL; ++ /* to clear e438 last value assigned not used , the compiler will optimize this code */ ++ (void)fltFmtHeap; ++ } ++ if (textLen < 0) { ++ /* bufferSize is large enough,just validation the return value */ ++ noOutput = 1; ++ break; ++ } ++ ++ formatAttr.fldWidth = textLen; /* no padding ,this variable to calculate amount of padding */ ++ prefixLen = 0; /* no padding ,this variable to calculate amount of padding */ ++ formatAttr.flags = 0; /* clear all internal formatAttr.flags */ ++ break; ++ } ++ } ++ ++ case SECUREC_CHAR('p'): ++ /* print a pointer */ ++#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) ++ formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; ++#else ++ formatAttr.flags |= SECUREC_FLAG_POINTER; ++#endif ++ ++#ifdef SECUREC_ON_64BITS ++ formatAttr.flags |= SECUREC_FLAG_I64; /* converting an int64 */ ++#else ++ formatAttr.flags |= SECUREC_FLAG_LONG; /* converting a long */ ++#endif ++ ++#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX)) ++ ++#if defined(SECUREC_VXWORKS_PLATFORM) ++ formatAttr.precision = 1; ++#else ++ formatAttr.precision = 0; ++#endif ++ formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */ ++ digits = itoaLowerDigits; ++ goto OUTPUT_HEX; ++#else ++/* not linux vxwoks */ ++#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) ++ formatAttr.precision = 1; ++#else ++ formatAttr.precision = 2 * sizeof(void *); ++#endif ++ ++#endif ++ ++#if defined(SECUREC_ON_UNIX) ++ digits = itoaLowerDigits; ++ goto OUTPUT_HEX; ++#endif ++ ++ [[fallthrough]]; ++ case SECUREC_CHAR('X'): ++ /* unsigned upper hex output */ ++ digits = itoaUpperDigits; ++ goto OUTPUT_HEX; ++ case SECUREC_CHAR('x'): ++ /* unsigned lower hex output */ ++ digits = itoaLowerDigits; ++ ++OUTPUT_HEX: ++ radix = 16; ++ if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { ++ /* alternate form means '0x' prefix */ ++ prefix[0] = SECUREC_CHAR('0'); ++ prefix[1] = (SecChar)(digits[16]); /* 'x' or 'X' */ ++ ++#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) ++ if (ch == 'p') { ++ prefix[1] = SECUREC_CHAR('x'); ++ } ++#endif ++#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) ++ if (ch == 'p') { ++ prefixLen = 0; ++ } else { ++ prefixLen = 2; ++ } ++#else ++ prefixLen = 2; ++#endif ++ ++ } ++ goto OUTPUT_INT; ++ case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ ++ case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ ++ /* signed decimal output */ ++ formatAttr.flags |= SECUREC_FLAG_SIGNED; ++ [[fallthrough]]; ++ case SECUREC_CHAR('u'): ++ radix = 10; ++ goto OUTPUT_INT; ++ case SECUREC_CHAR('o'): ++ /* unsigned octal output */ ++ radix = 8; ++ if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { ++ /* alternate form means force a leading 0 */ ++ formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL; ++ } ++OUTPUT_INT: ++ { ++ ++ SecUnsignedInt64 number = 0; /* number to convert */ ++ SecInt64 l; /* temp long value */ ++ unsigned char tch; ++#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS) ++ SecUnsignedInt32 digit = 0; /* ascii value of digit */ ++ SecUnsignedInt32 quotientHigh = 0; ++ SecUnsignedInt32 quotientLow = 0; ++#endif ++ ++ /* read argument into variable l */ ++ if (formatAttr.flags & SECUREC_FLAG_I64) { ++ l = (SecInt64)va_arg(arglist, SecInt64); ++ } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) { ++ l = (SecInt64)va_arg(arglist, SecInt64); ++ } else ++#ifdef SECUREC_ON_64BITS ++ if (formatAttr.flags & SECUREC_FLAG_LONG) { ++ l = (long)va_arg(arglist, long); ++ } else ++#endif /* SECUREC_ON_64BITS */ ++ if (formatAttr.flags & SECUREC_FLAG_CHAR) { ++ if (formatAttr.flags & SECUREC_FLAG_SIGNED) { ++ l = (char)va_arg(arglist, int); /* sign extend */ ++ if (l >= 128) { /* on some platform, char is always unsigned */ ++ SecUnsignedInt64 tmpL = (SecUnsignedInt64)l; ++ formatAttr.flags |= SECUREC_FLAG_NEGATIVE; ++ tch = (unsigned char)(~(tmpL)); ++ l = tch + 1; ++ } ++ } else { ++ l = (unsigned char)va_arg(arglist, int); /* zero-extend */ ++ } ++ ++ } else if (formatAttr.flags & SECUREC_FLAG_SHORT) { ++ if (formatAttr.flags & SECUREC_FLAG_SIGNED) { ++ l = (short)va_arg(arglist, int); /* sign extend */ ++ } else { ++ l = (unsigned short)va_arg(arglist, int); /* zero-extend */ ++ } ++ ++ } ++#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT ++ else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) { ++ l = (ptrdiff_t)va_arg(arglist, ptrdiff_t); /* sign extend */ ++ } else if (formatAttr.flags & SECUREC_FLAG_SIZE) { ++ if (formatAttr.flags & SECUREC_FLAG_SIGNED) { ++ /* No suitable macros were found to handle the branch */ ++ if (SecIsSameSize(sizeof(size_t), sizeof(long))) { ++ l = va_arg(arglist, long); /* sign extend */ ++ } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) { ++ l = va_arg(arglist, long long); /* sign extend */ ++ } else { ++ l = va_arg(arglist, int); /* sign extend */ ++ } ++ } else { ++ l = (SecInt64)(size_t)va_arg(arglist, size_t); /* sign extend */ ++ } ++ } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) { ++ if (formatAttr.flags & SECUREC_FLAG_SIGNED) { ++ l = va_arg(arglist, SecInt64); /* sign extend */ ++ } else { ++ l = (SecInt64)(SecUnsignedInt64)va_arg(arglist, SecUnsignedInt64); /* sign extend */ ++ } ++ } ++#endif ++ else { ++ if (formatAttr.flags & SECUREC_FLAG_SIGNED) { ++ l = va_arg(arglist, int); /* sign extend */ ++ } else { ++ l = (unsigned int)va_arg(arglist, int); /* zero-extend */ ++ } ++ ++ } ++ /*if it's a private arg, just write to stream*/ ++ if (isPrivacy == 1) { ++ break; ++ } ++ ++ /* check for negative; copy into number */ ++ if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) { ++ number = (SecUnsignedInt64)(-l); ++ formatAttr.flags |= SECUREC_FLAG_NEGATIVE; ++ } else { ++ number = (SecUnsignedInt64)l; ++ } ++ ++ if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) && ++#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT ++ ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) && ++#endif ++#ifdef SECUREC_ON_64BITS ++ ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) && ++ ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) && ++#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */ ++ ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) && ++#endif ++#endif ++ ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) { ++ ++ number &= 0xffffffff; ++ } ++ ++ /* check precision value for default */ ++ if (formatAttr.precision < 0) { ++ formatAttr.precision = 1; /* default precision */ ++ } else { ++#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) ++ formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; ++#else ++ if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) { ++ formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; ++ } ++#endif ++ if (formatAttr.precision > SECUREC_MAX_PRECISION) { ++ formatAttr.precision = SECUREC_MAX_PRECISION; ++ } ++ } ++ ++ /* Check if data is 0; if so, turn off hex prefix,if 'p',add 0x prefix,else not add prefix */ ++ if (number == 0) { ++#if !(defined(SECUREC_VXWORKS_PLATFORM)||defined(__hpux)) ++ prefixLen = 0; ++#else ++ if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE)) ++ prefixLen = 2; ++ else ++ prefixLen = 0; ++#endif ++ } ++ ++ /* Convert data to ASCII */ ++ formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE]; ++ ++ if (number > 0) { ++#ifdef SECUREC_ON_64BITS ++ switch (radix) { ++ /* the compiler will optimize each one */ ++ SECUREC_SPECIAL(number, 10); ++ break; ++ SECUREC_SPECIAL(number, 16); ++ break; ++ SECUREC_SPECIAL(number, 8); ++ break; ++ default: ++ break; ++ } ++#else /* for 32 bits system */ ++ if (number <= 0xFFFFFFFFUL) { ++ /* in most case, the value to be converted is small value */ ++ SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number; ++ switch (radix) { ++ SECUREC_SPECIAL(n32Tmp, 16); ++ break; ++ SECUREC_SPECIAL(n32Tmp, 8); ++ break; ++ ++#ifdef _AIX ++ /* the compiler will optimize div 10 */ ++ SECUREC_SPECIAL(n32Tmp, 10); ++ break; ++#else ++ case 10: ++ { ++ /* fast div 10 */ ++ SecUnsignedInt32 q; ++ SecUnsignedInt32 r; ++ do { ++ *--formatBuf.str = digits[n32Tmp % 10]; ++ q = (n32Tmp >> 1) + (n32Tmp >> 2); ++ q = q + (q >> 4); ++ q = q + (q >> 8); ++ q = q + (q >> 16); ++ q = q >> 3; ++ r = n32Tmp - (((q << 2) + q) << 1); ++ n32Tmp = (r > 9) ? (q + 1) : q; ++ } while (n32Tmp != 0); ++ } ++ break; ++#endif ++ default: ++ break; ++ } /* end switch */ ++ } else { ++ /* the value to be converted is greater than 4G */ ++#if defined(SECUREC_VXWORKS_VERSION_5_4) ++ do { ++ if (0 != SecU64Div32((SecUnsignedInt32)((number >> 16) >> 16), ++ (SecUnsignedInt32)number, ++ (SecUnsignedInt32)radix, "ientHigh, "ientLow, &digit)) { ++ noOutput = 1; ++ break; ++ } ++ *--formatBuf.str = digits[digit]; ++ ++ number = (SecUnsignedInt64)quotientHigh; ++ number = (number << 32) + quotientLow; ++ } while (number != 0); ++#else ++ switch (radix) { ++ /* the compiler will optimize div 10 */ ++ SECUREC_SPECIAL(number, 10); ++ break; ++ SECUREC_SPECIAL(number, 16); ++ break; ++ SECUREC_SPECIAL(number, 8); ++ break; ++ default: ++ break; ++ } ++#endif ++ } ++#endif ++ } /* END if (number > 0) */ ++ /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */ ++ textLen = (int)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str); ++ if (formatAttr.precision > textLen) { ++ for (ii = 0; ii < formatAttr.precision - textLen; ++ii) { ++ *--formatBuf.str = '0'; ++ } ++ textLen = formatAttr.precision; ++ } ++ ++ /* Force a leading zero if FORCEOCTAL flag set */ ++ if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) && (textLen == 0 || formatBuf.str[0] != '0')) { ++ *--formatBuf.str = '0'; ++ ++textLen; /* add a zero */ ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ /*if it's a private arg, just write to stream*/ ++ if (isPrivacy == 1) { ++ SecWritePrivateStr(stream, &charsOut); ++ break; ++ } ++ ++ if (noOutput == 0) { ++ if (formatAttr.flags & SECUREC_FLAG_SIGNED) { ++ if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) { ++ /* prefix is a '-' */ ++ prefix[0] = SECUREC_CHAR('-'); ++ prefixLen = 1; ++ } else if (formatAttr.flags & SECUREC_FLAG_SIGN) { ++ /* prefix is '+' */ ++ prefix[0] = SECUREC_CHAR('+'); ++ prefixLen = 1; ++ } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) { ++ /* prefix is ' ' */ ++ prefix[0] = SECUREC_CHAR(' '); ++ prefixLen = 1; ++ } ++ } ++ ++#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX)) ++ if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (0 == textLen)) { ++ formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; ++ formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1]; ++ *formatBuf.str-- = '\0'; ++ *formatBuf.str-- = ')'; ++ *formatBuf.str-- = 'l'; ++ *formatBuf.str-- = 'i'; ++ *formatBuf.str-- = 'n'; ++ *formatBuf.str = '('; ++ textLen = 5; ++ } ++#endif ++ ++ /* calculate amount of padding */ ++ padding = (formatAttr.fldWidth - textLen) - prefixLen; ++ ++ /* put out the padding, prefix, and text, in the correct order */ ++ ++ if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) { ++ /* pad on left with blanks */ ++ if (SECUREC_IS_REST_BUF_ENOUGH(padding)) { ++ /* char * cast to wchar * */ ++ SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); ++ } else { ++ SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); ++ } ++ } ++ ++ /* write prefix */ ++ if (prefixLen > 0) { ++ SecChar *pPrefix = prefix; ++ if (SECUREC_IS_REST_BUF_ENOUGH(prefixLen)) { ++ /* max prefix len is 2, use loop copy */ /* char * cast to wchar * */ ++ SECUREC_SAFE_WRITE_PREFIX(pPrefix, prefixLen, stream, &charsOut); ++ } else { ++ SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut); ++ } ++ } ++ ++ if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT) ++ && padding > 0) { ++ /* write leading zeros */ ++ if (SECUREC_IS_REST_BUF_ENOUGH(padding)) { ++ /* char * cast to wchar * */ ++ SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut); ++ } else { ++ SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut); ++ } ++ } ++ ++ /* write text */ ++#ifndef SECUREC_FOR_WCHAR ++ if (formatAttr.bufferIsWide && (textLen > 0)) { ++ wchar_t *p = formatBuf.wStr; ++ int count = textLen; ++ while (count--) { ++ char tmpBuf[SECUREC_MB_LEN + 1]; ++ SECUREC_MASK_MSVC_CRT_WARNING ++ int retVal = wctomb(tmpBuf, *p++); ++ SECUREC_END_MASK_MSVC_CRT_WARNING ++ if (retVal <= 0) { ++ charsOut = -1; ++ break; ++ } ++ SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut); ++ } ++ } else { ++ if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) { ++ SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut); ++ } else { ++ SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut); ++ } ++ } ++#else /* SECUREC_FOR_WCHAR */ ++ if (formatAttr.bufferIsWide == 0 && textLen > 0) { ++ int count = textLen; ++ char *p = formatBuf.str; ++ ++ while (count > 0) { ++ wchar_t wchar = L'\0'; ++ int retVal = mbtowc(&wchar, p, (size_t)MB_CUR_MAX); ++ if (retVal <= 0) { ++ charsOut = -1; ++ break; ++ } ++ SECUREC_WRITE_CHAR(wchar, stream, &charsOut); ++ p += retVal; ++ count -= retVal; ++ } ++ } else { ++ if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) { ++ SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut); /* char * cast to wchar * */ ++ } else { ++ SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut); ++ } ++ } ++#endif /* SECUREC_FOR_WCHAR */ ++ ++ if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) { ++ /* pad on right with blanks */ ++ if (SECUREC_IS_REST_BUF_ENOUGH(padding)) { ++ /* char * cast to wchar * */ ++ SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut); ++ } else { ++ SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut); ++ } ++ } ++ ++ /* we're done! */ ++ } ++ if (floatBuf != NULL) { ++ SECUREC_FREE(floatBuf); ++ floatBuf = NULL; ++ } ++ break; ++ case STAT_INVALID: ++ return -1; ++ default: ++ return -1; /* input format is wrong, directly return */ ++ } ++ } ++ ++ if (state != STAT_NORMAL && state != STAT_TYPE) { ++ return -1; ++ } ++ ++ return charsOut; /* the number of characters written */ ++} /* arglist must not be declare as const */ ++#endif /* OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */ +diff --git a/hilog.gni b/hilog.gni +index 116b058..bdd9393 100644 +--- a/hilog.gni ++++ b/hilog.gni +@@ -12,9 +12,9 @@ + # limitations under the License. + + platforms = [ +- "ohos", +- "windows", +- "mac", ++ # "ohos", ++ # "windows", ++ # "mac", + "linux", + ] + +diff --git a/interfaces/bundle.json b/interfaces/bundle.json +index f6b5cdf..330ffcb 100644 +--- a/interfaces/bundle.json ++++ b/interfaces/bundle.json +@@ -39,10 +39,7 @@ + "base_group": [ + + ], +- "fwk_group": [ +- "//base/hiviewdfx/hilog/frameworks/hilog_ndk:hilog_ndk", +- "//base/hiviewdfx/hilog/interfaces/js:hilog_napi" +- ], ++ "fwk_group": [], + "service_group": [ + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_base", + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog" +diff --git a/interfaces/native/innerkits/BUILD.gn b/interfaces/native/innerkits/BUILD.gn +index 3666081..ee27551 100644 +--- a/interfaces/native/innerkits/BUILD.gn ++++ b/interfaces/native/innerkits/BUILD.gn +@@ -19,40 +19,33 @@ config("libhilog_pub_config") { + include_dirs = [ "include" ] + } + +-template("libhilog") { +- forward_variables_from(invoker, "*") +- ohos_shared_library(target_name) { ++ohos_shared_library("libhilog") { + public_configs = [ ":libhilog_pub_config" ] +- +- deps = [ +- "//base/hiviewdfx/hilog/frameworks/libhilog:libhilog_source_$platform", ++ sources = [ ++ "//base/hiviewdfx/hilog/libhilog/hilog.cpp", ++ "//base/hiviewdfx/hilog/libhilog/vsnprintf/vsnprintf_s_p.cpp", ++ "//base/hiviewdfx/hilog/libhilog/utils/log_utils.cpp", ++ "//base/hiviewdfx/hilog/libhilog/utils/log_print.cpp", + ] + +- if (platform == "ohos") { +- output_extension = "so" +- } ++ include_dirs = [ ++ "//base/hiviewdfx/hilog/libhilog/include/", ++ "//base/hiviewdfx/hilog/libhilog/vsnprintf/include/", ++ "//base/hiviewdfx/hilog/libhilog/utils/include/", ++ ] + ++ defines = [] ++ cflags_cc = [ "-std=c++17", "-fpermissive" ] ++ defines += [ "__LINUX__" ] ++ deps = [ ++ "//third_party/bounds_checking_function:libsec_shared" ++ ] + install_enable = !hilog_native_feature_ohcore + install_images = [ + "system", +- "updater", + ] + part_name = "hilog_native" + subsystem_name = "hiviewdfx" +- } +-} +- +-foreach(item, platforms) { +- if (item == "ohos") { +- libhilog("libhilog") { +- platform = item +- } +- } +- if (item == "windows" || item == "mac" || item == "linux") { +- libhilog("libhilog_" + item) { +- platform = item +- } +- } + } + + config("libhilog_base_pub_cfg") { +diff --git a/interfaces/native/innerkits/include/hilog/log_c.h b/interfaces/native/innerkits/include/hilog/log_c.h +index 2649f33..08aa937 100644 +--- a/interfaces/native/innerkits/include/hilog/log_c.h ++++ b/interfaces/native/innerkits/include/hilog/log_c.h +@@ -57,8 +57,8 @@ typedef enum { + + const char* GetLastFatalMessage(void); + +-int HiLogPrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...) +- __attribute__((__format__(os_log, 5, 6))); ++int HiLogPrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...); ++ // __attribute__((__format__(os_log, 5, 6))); + + #define HILOG_DEBUG(type, ...) ((void)HiLogPrint((type), LOG_DEBUG, LOG_DOMAIN, LOG_TAG, __VA_ARGS__)) + +diff --git a/interfaces/native/innerkits/include/hilog/log_cpp.h b/interfaces/native/innerkits/include/hilog/log_cpp.h +index ff48162..bc6077e 100644 +--- a/interfaces/native/innerkits/include/hilog/log_cpp.h ++++ b/interfaces/native/innerkits/include/hilog/log_cpp.h +@@ -21,7 +21,7 @@ + #ifdef __cplusplus + namespace OHOS { + namespace HiviewDFX { +-using HiLogLabel = struct { ++struct HiLogLabel { + LogType type; + unsigned int domain; + const char *tag; +@@ -29,11 +29,16 @@ using HiLogLabel = struct { + + class HiLog final { + public: +- static int Debug(const HiLogLabel &label, const char *fmt, ...) __attribute__((__format__(os_log, 2, 3))); +- static int Info(const HiLogLabel &label, const char *fmt, ...) __attribute__((__format__(os_log, 2, 3))); +- static int Warn(const HiLogLabel &label, const char *fmt, ...) __attribute__((__format__(os_log, 2, 3))); +- static int Error(const HiLogLabel &label, const char *fmt, ...) __attribute__((__format__(os_log, 2, 3))); +- static int Fatal(const HiLogLabel &label, const char *fmt, ...) __attribute__((__format__(os_log, 2, 3))); ++ static int Debug(const HiLogLabel &label, const char *fmt, ...); ++ // __attribute__((__format__(os_log, 2, 3))); ++ static int Info(const HiLogLabel &label, const char *fmt, ...); ++ // __attribute__((__format__(os_log, 2, 3))); ++ static int Warn(const HiLogLabel &label, const char *fmt, ...); ++ // __attribute__((__format__(os_log, 2, 3))); ++ static int Error(const HiLogLabel &label, const char *fmt, ...); ++ // __attribute__((__format__(os_log, 2, 3))); ++ static int Fatal(const HiLogLabel &label, const char *fmt, ...); ++ // __attribute__((__format__(os_log, 2, 3))); + }; + } // namespace HiviewDFX + } // namespace OHOS +-- +2.33.0 + diff --git a/0002-fix-build-gn-files-config.patch b/0002-fix-build-gn-files-config.patch new file mode 100644 index 0000000000000000000000000000000000000000..502ed438385c98fc75cca9aa62f54df028e04383 --- /dev/null +++ b/0002-fix-build-gn-files-config.patch @@ -0,0 +1,67 @@ +From d0d35591b378d879f1659f4bfd082b165b31e8f1 Mon Sep 17 00:00:00 2001 +From: tian2020 +Date: Wed, 14 Jun 2023 19:55:41 +0800 +Subject: [PATCH 2/3] fix build gn files config + +--- + interfaces/native/innerkits/BUILD.gn | 34 +++++++++++++++++++++------- + 1 file changed, 26 insertions(+), 8 deletions(-) + +diff --git a/interfaces/native/innerkits/BUILD.gn b/interfaces/native/innerkits/BUILD.gn +index ee27551..c74beda 100644 +--- a/interfaces/native/innerkits/BUILD.gn ++++ b/interfaces/native/innerkits/BUILD.gn +@@ -22,16 +22,16 @@ config("libhilog_pub_config") { + ohos_shared_library("libhilog") { + public_configs = [ ":libhilog_pub_config" ] + sources = [ +- "//base/hiviewdfx/hilog/libhilog/hilog.cpp", +- "//base/hiviewdfx/hilog/libhilog/vsnprintf/vsnprintf_s_p.cpp", +- "//base/hiviewdfx/hilog/libhilog/utils/log_utils.cpp", +- "//base/hiviewdfx/hilog/libhilog/utils/log_print.cpp", ++ "//base/hiviewdfx/hilog/frameworks/libhilog/hilog.cpp", ++ "//base/hiviewdfx/hilog/frameworks/libhilog/vsnprintf/vsnprintf_s_p.cpp", ++ "//base/hiviewdfx/hilog/frameworks/libhilog/utils/log_utils.cpp", ++ "//base/hiviewdfx/hilog/frameworks/libhilog/utils/log_print.cpp", + ] + + include_dirs = [ +- "//base/hiviewdfx/hilog/libhilog/include/", +- "//base/hiviewdfx/hilog/libhilog/vsnprintf/include/", +- "//base/hiviewdfx/hilog/libhilog/utils/include/", ++ "//base/hiviewdfx/hilog/frameworks/libhilog/include/", ++ "//base/hiviewdfx/hilog/frameworks/libhilog/vsnprintf/include/", ++ "//base/hiviewdfx/hilog/frameworks/libhilog/utils/include/", + ] + + defines = [] +@@ -56,7 +56,25 @@ config("libhilog_base_pub_cfg") { + ohos_static_library("libhilog_base") { + public_configs = [ ":libhilog_base_pub_cfg" ] + +- deps = [ "//base/hiviewdfx/hilog/frameworks/libhilog:libhilog_base_source" ] ++ #deps = [ "//base/hiviewdfx/hilog/frameworks/libhilog:libhilog_base_source" ] ++ ++ include_dirs = [ ++ "//base/hiviewdfx/hilog/frameworks/libhilog/vsnprintf/include", ++ "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", ++ ] ++ ++ # vsnprintf_sources = [ "$vsnprintf_root/vsnprintf_s_p.cpp" ] ++ ++ sources = [ "//base/hiviewdfx/hilog/frameworks/libhilog/base/hilog_base.cpp" ] ++ # sources += vsnprintf_sources ++ ++ public_configs += [ "//base/hiviewdfx/hilog/frameworks/libhilog/:libhilog_base_config" ] ++ configs = [ "//base/hiviewdfx/hilog/frameworks/libhilog/:libhilog_base_config" ] ++ ++ defines = [ ++ "__RECV_MSG_WITH_UCRED_", ++ "HILOG_PROHIBIT_ALLOCATION", ++ ] + + subsystem_name = "hiviewdfx" + part_name = "hilog_native" +-- +2.33.0 + diff --git a/0003-feat-set-priv-false.patch b/0003-feat-set-priv-false.patch new file mode 100644 index 0000000000000000000000000000000000000000..054c976ae78f4cf1c311c07c29027a88bdd3cf35 --- /dev/null +++ b/0003-feat-set-priv-false.patch @@ -0,0 +1,30 @@ +From bcefda18f27ea4c427ad11ac1ae373e503787fca Mon Sep 17 00:00:00 2001 +From: tian2020 +Date: Thu, 15 Jun 2023 10:52:07 +0800 +Subject: [PATCH 3/3] feat set priv false + +--- + frameworks/libhilog/hilog_printf.cpp | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/frameworks/libhilog/hilog_printf.cpp b/frameworks/libhilog/hilog_printf.cpp +index 1316128..ccfef1d 100644 +--- a/frameworks/libhilog/hilog_printf.cpp ++++ b/frameworks/libhilog/hilog_printf.cpp +@@ -219,12 +219,7 @@ int HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int + } + + /* format log string */ +-#if not (defined( __WINDOWS__ ) || defined( __MAC__ ) || defined( __LINUX__ )) +- bool debug = IsDebugOn(); +- bool priv = (!debug) && IsPrivateSwitchOn(); +-#else +- bool priv = true; +-#endif ++ bool priv = false; + + #ifdef __clang__ + /* code specific to clang compiler */ +-- +2.33.0 + diff --git a/0004-close-private-print-in-hilog.cpp-file.patch b/0004-close-private-print-in-hilog.cpp-file.patch new file mode 100644 index 0000000000000000000000000000000000000000..334a92d20f9c0daa8d51ec00034b6a0409d55e95 --- /dev/null +++ b/0004-close-private-print-in-hilog.cpp-file.patch @@ -0,0 +1,25 @@ +From 4109037a7f708c6d23ccdff64a5638ef592c7598 Mon Sep 17 00:00:00 2001 +From: heppen +Date: Mon, 31 Jul 2023 10:24:25 +0800 +Subject: [PATCH] Close private print in hilog.cpp file + +--- + frameworks/libhilog/hilog.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/frameworks/libhilog/hilog.cpp b/frameworks/libhilog/hilog.cpp +index e58c6d6..8da82c5 100644 +--- a/frameworks/libhilog/hilog.cpp ++++ b/frameworks/libhilog/hilog.cpp +@@ -77,7 +77,7 @@ int HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int + char *logBuf = buf; + int traceBufLen = 0; + int ret; +- bool priv = true; ++ bool priv = false; + + #ifdef __clang__ + /* code specific to clang compiler */ +-- +2.33.0 + diff --git a/hilog.spec b/hilog.spec new file mode 100644 index 0000000000000000000000000000000000000000..5d707742b59e54b66c121be745001f1febe9c082 --- /dev/null +++ b/hilog.spec @@ -0,0 +1,90 @@ +%define debug_package %{nil} +%global openHarmony_source_release OpenHarmony-v3.2-Release +%global hilog_dir %{_builddir}/base/hiviewdfx +%global build_opt /opt/distributed-middleware-build + +Name: hilog +Version: 1.0.0 +Release: 2 +Summary: OpenEuler supports hilog for distributed softbus capability +License: Apache License 2.0 +Url: https://gitee.com/openharmony/hiviewdfx_hilog +Source0: https://gitee.com/openharmony/hiviewdfx_hilog/repository/archive/%{openHarmony_source_release}.tar.gz #/hiviewdfx_hilog-%{openHarmony_source_release}.tar.gz +Patch0000: 0001-init-and-adapt-to-openeuler.patch +Patch0001: 0002-fix-build-gn-files-config.patch +Patch0002: 0003-feat-set-priv-false.patch +Patch0003: 0004-close-private-print-in-hilog.cpp-file.patch + +BuildRequires: distributed-build, libboundscheck,libatomic +Requires: libboundscheck, libatomic + +%description +OpenEuler supports hilog for distributed softbus capability + +%prep +#clean %{_builddir} +rm -rf %{_builddir}/* +%autosetup -p1 -n hiviewdfx_hilog-%{openHarmony_source_release} + +cd %{_builddir} +mkdir -p %{hilog_dir} +mv hiviewdfx_hilog-%{openHarmony_source_release} %{hilog_dir}/hilog + +# build directory +cp -rp %{build_opt} %{_builddir}/build +[ ! -L "%{_builddir}/build.sh" ] && ln -s %{_builddir}/build/build_scripts/build.sh %{_builddir}/build.sh +[ ! -L "%{_builddir}/.gn" ] && ln -s %{_builddir}/build/core/gn/dotfile.gn %{_builddir}/.gn +[ ! -L "%{_builddir}/build.py" ] && ln -s %{_builddir}/build/lite/build.py %{_builddir}/build.py +cp -r %{_builddir}/build/openeuler/vendor %{_builddir}/ +cp -r %{_builddir}/build/openeuler/compiler_gn/third_party %{_builddir}/ + +#directory to avoid %build fail +mkdir hiviewdfx_hilog-%{openHarmony_source_release} + +%build +cd %{_builddir} +rm -rf %{_builddir}/out + +%ifarch x86_64 +./build.sh --product-name openeuler --target-cpu x86_64 +%endif + +%ifarch aarch64 +./build.sh --product-name openeuler --target-cpu arm64 +%endif + +%install +install -d %{buildroot}/%{_includedir}/hilog +install -d %{buildroot}/%{_includedir}/hilog/hilog +install -d %{buildroot}/%{_includedir}/hilog/hilog_base +install -d %{buildroot}/%{_libdir} + +# prepare so +install -m 0755 %{_builddir}/out/openeuler/packages/phone/system/lib64/libhilog*.so %{buildroot}/%{_libdir} + +%ifarch x86_64 +install -m 0755 %{_builddir}/out/openeuler/linux_clang_x86_64/obj/base/hiviewdfx/hilog/interfaces/native/innerkits/libhilog_base.a %{buildroot}/%{_libdir} +%endif + +%ifarch aarch64 +install -m 0755 %{_builddir}/out/openeuler/linux_clang_arm64/obj/base/hiviewdfx/hilog/interfaces/native/innerkits/libhilog_base.a %{buildroot}/%{_libdir} +%endif + +# prepare head files according to bundle.json +install -m 554 %{hilog_dir}/hilog/interfaces/native/innerkits/include/*.h %{buildroot}/%{_includedir}/hilog +install -m 554 %{hilog_dir}/hilog/interfaces/native/innerkits/include/hilog/*.h %{buildroot}/%{_includedir}/hilog/hilog +install -m 554 %{hilog_dir}/hilog/interfaces/native/innerkits/include/hilog_base/*.h %{buildroot}/%{_includedir}/hilog/hilog_base + +%files +%{_includedir}/hilog/* +%{_libdir}/*.so +%{_libdir}/*.a + +%changelog + +* Mon Jul 31 2023 Peng He - 1.0.0-2 +- Close private print in hilog.cpp file. + +* Thu Jun 15 2023 tianhang - 1.0.0-1 +- Init and adapt to openeuler + diff --git a/hiviewdfx_hilog-OpenHarmony-v3.2-Release.tar.gz b/hiviewdfx_hilog-OpenHarmony-v3.2-Release.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b63046f3dee2c4f1e5b8148a3bb35b77061fc2fc Binary files /dev/null and b/hiviewdfx_hilog-OpenHarmony-v3.2-Release.tar.gz differ