1 /*
2 * Copyright (c) 2021-2022 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 "init_log.h"
17
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdarg.h>
21 #include <sys/stat.h>
22 #include <time.h>
23 #include <sys/time.h>
24
25 #include "init_utils.h"
26 #include "securec.h"
27 #ifdef OHOS_LITE
28 #ifndef INIT_LOG_INIT
29 #define INIT_LOG_INIT LOG_CORE
30 #endif
31 #include "hilog/log.h"
32 #endif
33 #ifdef INIT_AGENT
34 #include "hilog_base/log_base.h"
35 #endif
36
37 #define DEF_LOG_SIZE 128
38 #define BASE_YEAR 1900
39
40 static InitLogLevel g_logLevel = INIT_INFO;
41 #ifdef INIT_FILE
LogToFile(const char * logFile,const char * tag,const char * info)42 static void LogToFile(const char *logFile, const char *tag, const char *info)
43 {
44 struct timespec curr = {0};
45 if (clock_gettime(CLOCK_REALTIME, &curr) != 0) {
46 return;
47 }
48 FILE *outfile = NULL;
49 INIT_CHECK_ONLY_RETURN((outfile = fopen(logFile, "a+")) != NULL);
50 struct tm t;
51 char dateTime[80] = {"00-00-00 00:00:00"}; // 80 data time
52 if (localtime_r(&curr.tv_sec, &t) != NULL) {
53 strftime(dateTime, sizeof(dateTime), "%Y-%m-%d %H:%M:%S", &t);
54 }
55 (void)fprintf(outfile, "[%s.%ld][pid=%d %d][%s]%s \n", dateTime, curr.tv_nsec, getpid(), gettid(), tag, info);
56 (void)fflush(outfile);
57 fclose(outfile);
58 return;
59 }
60 #endif
61
62 #ifdef INIT_DMESG
63 static int g_fd = -1;
OpenLogDevice(void)64 INIT_LOCAL_API void OpenLogDevice(void)
65 {
66 int fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
67 if (fd >= 0) {
68 g_fd = fd;
69 }
70 return;
71 }
72
LogToDmesg(InitLogLevel logLevel,const char * tag,const char * info)73 void LogToDmesg(InitLogLevel logLevel, const char *tag, const char *info)
74 {
75 static const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
76 static const char *LOG_KLEVEL_STR[] = { "<7>", "<6>", "<4>", "<3>", "<3>" };
77
78 if (UNLIKELY(g_fd < 0)) {
79 OpenLogDevice();
80 if (g_fd < 0) {
81 return;
82 }
83 }
84 char logInfo[DEF_LOG_SIZE + DEF_LOG_SIZE] = {0};
85 if (snprintf_s(logInfo, sizeof(logInfo), sizeof(logInfo) - 1, "%s[pid=%d][%s][%s]%s",
86 LOG_KLEVEL_STR[logLevel], getpid(), tag, LOG_LEVEL_STR[logLevel], info) == -1) {
87 logInfo[sizeof(logInfo) - 2] = '\n'; // 2 add \n to tail
88 logInfo[sizeof(logInfo) - 1] = '\0';
89 return;
90 }
91 if (write(g_fd, logInfo, strlen(logInfo)) < 0) {
92 printf("%s\n", logInfo);
93 }
94 return;
95 }
96 #endif
97
PrintLog(InitLogLevel logLevel,unsigned int domain,const char * tag,const char * logInfo)98 static void PrintLog(InitLogLevel logLevel, unsigned int domain, const char *tag, const char *logInfo)
99 {
100 #if defined(__LITEOS_A__) || defined(__LINUX__)
101 static const LogLevel LOG_LEVEL[] = { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };
102 (void)HiLogPrint(INIT_LOG_INIT, LOG_LEVEL[logLevel], domain, tag, "%s", logInfo);
103 #endif
104 #ifdef INIT_DMESG
105 LogToDmesg(logLevel, tag, logInfo);
106 #endif
107 #ifdef INIT_AGENT
108 static const LogLevel LOG_LEVEL[] = { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };
109 HiLogBasePrint(LOG_CORE, LOG_LEVEL[logLevel], domain, tag, "%{public}s", logInfo);
110 #endif
111 #ifdef INIT_FILE
112 LogToFile(INIT_LOG_PATH"begetctl.log", tag, logInfo);
113 #endif
114 }
115
PrintLogFmt(int logLevel,unsigned int domain,const char * tag,const char * fmt,va_list vargs)116 static void PrintLogFmt(int logLevel, unsigned int domain, const char *tag, const char *fmt, va_list vargs)
117 {
118 char tmpFmt[DEF_LOG_SIZE] = {0};
119 if (vsnprintf_s(tmpFmt, sizeof(tmpFmt), sizeof(tmpFmt) - 1, fmt, vargs) == -1) {
120 tmpFmt[sizeof(tmpFmt) - 2] = '\n'; // 2 add \n to tail
121 tmpFmt[sizeof(tmpFmt) - 1] = '\0';
122 }
123 PrintLog((InitLogLevel)logLevel, domain, tag, tmpFmt);
124 }
125
InitLog(int logLevel,unsigned int domain,const char * tag,const char * fmt,va_list vargs)126 INIT_LOCAL_API void InitLog(int logLevel, unsigned int domain, const char *tag, const char *fmt, va_list vargs)
127 {
128 if ((int)g_logLevel > logLevel) {
129 return;
130 }
131 PrintLogFmt((InitLogLevel)logLevel, domain, tag, fmt, vargs);
132 }
133
SetInitLogLevel(InitLogLevel level)134 INIT_PUBLIC_API void SetInitLogLevel(InitLogLevel level)
135 {
136 if (level <= INIT_FATAL) {
137 g_logLevel = level;
138 }
139 return;
140 }
141
EnableInitLog(InitLogLevel level)142 INIT_LOCAL_API void EnableInitLog(InitLogLevel level)
143 {
144 g_logLevel = level;
145 SetInitCommLog(InitLog);
146 }
147
GetInitLogLevel()148 INIT_PUBLIC_API InitLogLevel GetInitLogLevel()
149 {
150 return g_logLevel;
151 }
152