xref: /base/startup/init/services/log/init_log.c (revision d9f0492f)
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
40static InitLogLevel g_logLevel = INIT_INFO;
41#ifdef INIT_FILE
42static 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    (void)fclose(outfile);
58    return;
59}
60#endif
61
62#ifdef INIT_DMESG
63static int g_fd = -1;
64INIT_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
73void 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
97INIT_PUBLIC_API int GetKmsgFd()
98{
99    return g_fd;
100}
101#endif
102
103static void PrintLog(InitLogLevel logLevel, unsigned int domain, const char *tag, const char *logInfo)
104{
105#if defined(__LITEOS_A__) || defined(__LINUX__)
106    static const LogLevel LOG_LEVEL[] = { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };
107    (void)HiLogPrint(INIT_LOG_INIT, LOG_LEVEL[logLevel], domain, tag, "%s", logInfo);
108#endif
109#ifdef INIT_DMESG
110    LogToDmesg(logLevel, tag, logInfo);
111#endif
112#ifdef INIT_AGENT
113    static const LogLevel LOG_LEVEL[] = { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };
114    HiLogBasePrint(LOG_CORE, LOG_LEVEL[logLevel], domain, tag, "%{public}s", logInfo);
115#endif
116#ifdef INIT_FILE
117    LogToFile(INIT_LOG_PATH"begetctl.log", tag, logInfo);
118#endif
119}
120
121static void PrintLogFmt(int logLevel, unsigned int domain, const char *tag, const char *fmt, va_list vargs)
122{
123    char tmpFmt[DEF_LOG_SIZE] = {0};
124    if (vsnprintf_s(tmpFmt, sizeof(tmpFmt), sizeof(tmpFmt) - 1, fmt, vargs) == -1) {
125        tmpFmt[sizeof(tmpFmt) - 2] = '\n'; // 2 add \n to tail
126        tmpFmt[sizeof(tmpFmt) - 1] = '\0';
127    }
128    PrintLog((InitLogLevel)logLevel, domain, tag, tmpFmt);
129}
130
131INIT_LOCAL_API void InitLog(int logLevel, unsigned int domain, const char *tag, const char *fmt, va_list vargs)
132{
133    if ((int)g_logLevel > logLevel) {
134        return;
135    }
136    PrintLogFmt((InitLogLevel)logLevel, domain, tag, fmt, vargs);
137}
138
139INIT_PUBLIC_API void SetInitLogLevel(InitLogLevel level)
140{
141    if (level <= INIT_FATAL) {
142        g_logLevel = level;
143    }
144    return;
145}
146
147INIT_LOCAL_API void EnableInitLog(InitLogLevel level)
148{
149    g_logLevel = level;
150    SetInitCommLog(InitLog);
151}
152
153INIT_PUBLIC_API InitLogLevel GetInitLogLevel()
154{
155    return g_logLevel;
156}
157