• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
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 #ifdef OHOS_LITE
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 
InitLog(int logLevel,unsigned int domain,const char * tag,const char * fmt,va_list vargs)116 INIT_LOCAL_API void InitLog(int logLevel, unsigned int domain, const char *tag, const char *fmt, va_list vargs)
117 {
118     if ((int)g_logLevel > logLevel) {
119         return;
120     }
121     char tmpFmt[DEF_LOG_SIZE] = {0};
122     if (vsnprintf_s(tmpFmt, sizeof(tmpFmt), sizeof(tmpFmt) - 1, fmt, vargs) == -1) {
123         tmpFmt[sizeof(tmpFmt) - 2] = '\n'; // 2 add \n to tail
124         tmpFmt[sizeof(tmpFmt) - 1] = '\0';
125     }
126     PrintLog((InitLogLevel)logLevel, domain, tag, tmpFmt);
127 }
128 
SetInitLogLevel(InitLogLevel level)129 INIT_PUBLIC_API void SetInitLogLevel(InitLogLevel level)
130 {
131     if (level <= INIT_FATAL) {
132         g_logLevel = level;
133     }
134     return;
135 }
136 
EnableInitLog(InitLogLevel level)137 INIT_LOCAL_API void EnableInitLog(InitLogLevel level)
138 {
139     g_logLevel = level;
140     SetInitCommLog(InitLog);
141 }
142 
EnableInitLogFromCmdline(void)143 INIT_LOCAL_API void EnableInitLogFromCmdline(void)
144 {
145     SetInitCommLog(InitLog);
146     char level[MAX_BUFFER_LEN] = {0};
147     char *buffer = ReadFileData("/proc/cmdline");
148     if (buffer == NULL) {
149         INIT_LOGE("Failed to read \"/proc/cmdline\"");
150         return;
151     }
152     int ret = GetProcCmdlineValue("initloglevel", buffer, level, MAX_BUFFER_LEN);
153     free(buffer);
154     if (ret != 0) {
155         INIT_LOGE("Failed get log level from cmdline");
156         return;
157     }
158     errno = 0;
159     unsigned int logLevel = (unsigned int)strtoul(level, 0, 10); // 10 is decimal
160     INIT_INFO_CHECK(errno == 0, return, "Failed strtoul %s, err=%d", level, errno);
161     SetInitLogLevel((InitLogLevel)logLevel);
162     return;
163 }
164