1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "dfx_log.h"
17 
18 #include <cstdarg>
19 #include <cstdio>
20 #include <fcntl.h>
21 #include <securec.h>
22 #include <unistd.h>
23 #include "dfx_define.h"
24 
25 static int g_debugFd = INVALID_FD;
26 static LogLevel g_logLevel = LogLevel::LOG_INFO;
27 
28 #ifdef DFX_LOG_DMESG
29 static int g_dmesgFd = INVALID_FD;
30 
CloseDmesg()31 static void CloseDmesg()
32 {
33     if (g_dmesgFd > 0) {
34         close(g_dmesgFd);
35         g_dmesgFd = -1;
36     }
37 }
38 
LogToDmesg(const LogLevel logLevel,const char * tag,const char * info)39 static void LogToDmesg(const LogLevel logLevel, const char *tag, const char *info)
40 {
41     static const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
42     static const char *LOG_KLEVEL_STR[] = { "<7>", "<6>", "<4>", "<3>", "<3>" };
43     int dmesgLevel = static_cast<int>(logLevel) - LOG_DEBUG;
44 
45     if (UNLIKELY(g_dmesgFd < 0)) {
46         g_dmesgFd = open("/dev/kmsg", O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
47     }
48     char buf[LOG_BUF_LEN] = {0};
49 #if is_ohos
50     if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%s[pid=%d %d][%s][%s]%s",
51         LOG_KLEVEL_STR[dmesgLevel], getprocpid(), getppid(), tag, LOG_LEVEL_STR[dmesgLevel], info) < 0) {
52         CloseDmesg();
53         return;
54     }
55 #else
56     if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%s[pid=%d %d][%s][%s]%s",
57         LOG_KLEVEL_STR[dmesgLevel], getpid(), getppid(), tag, LOG_LEVEL_STR[dmesgLevel], info) < 0) {
58         CloseDmesg();
59         return;
60     }
61 #endif
62 
63     if (OHOS_TEMP_FAILURE_RETRY(write(g_dmesgFd, buf, strlen(buf))) < 0) {
64         CloseDmesg();
65     }
66 }
67 #endif
68 
InitDebugFd(int fd)69 void InitDebugFd(int fd)
70 {
71     g_debugFd = fd;
72 }
73 
CheckDebugLevel(void)74 bool CheckDebugLevel(void)
75 {
76     return LogLevel::LOG_DEBUG >= g_logLevel ? true : false;
77 }
78 
SetLogLevel(const LogLevel logLevel)79 void SetLogLevel(const LogLevel logLevel)
80 {
81     g_logLevel = logLevel;
82 }
83 
GetLogLevel(void)84 LogLevel GetLogLevel(void)
85 {
86     return g_logLevel;
87 }
88 
DfxLogPrint(const LogLevel logLevel,const unsigned int domain,const char * tag,const char * fmt,...)89 int DfxLogPrint(const LogLevel logLevel, const unsigned int domain, const char* tag, const char *fmt, ...)
90 {
91 #ifndef DFX_LOG_UNWIND
92     if (logLevel < g_logLevel) {
93         return -1;
94     }
95 #endif
96     int ret = -1;
97 #if defined(DFX_LOG_HILOG_BASE) || defined(is_ohos_lite)
98     va_list args;
99     va_start(args, fmt);
100     ret = DfxLogPrintV(logLevel, domain, tag, fmt, args);
101     va_end(args);
102 #endif
103     return ret;
104 }
105 
DfxLogPrintV(const LogLevel logLevel,const unsigned int domain,const char * tag,const char * fmt,va_list ap)106 int DfxLogPrintV(const LogLevel logLevel, const unsigned int domain, const char* tag, const char *fmt, va_list ap)
107 {
108     if ((logLevel < LogLevel::LOG_DEBUG) || (logLevel > LogLevel::LOG_FATAL)) {
109         return -1;
110     }
111 
112     char buf[LOG_BUF_LEN] = {0};
113     int ret = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, ap);
114     if (ret == -1) {
115         return ret;
116     }
117 #ifdef DFX_LOG_HILOG_BASE
118     HiLogBasePrint(LOG_CORE, logLevel, domain, tag, "%{public}s", buf);
119 #else
120     HiLogPrint(LOG_CORE, logLevel, domain, tag, "%{public}s", buf);
121 #endif
122 
123 #ifdef DFX_LOG_DMESG
124     LogToDmesg(logLevel, tag, buf);
125 #endif
126 
127     if (g_debugFd != INVALID_FD) {
128         fprintf(stderr, "%s\n", buf);
129     }
130     return ret;
131 }