1 /*
2 * Copyright (c) 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 "hilog_base/log_base.h"
17 #include <hilog_base.h>
18 #include <vsnprintf_s_p.h>
19
20 #include <errno.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/socket.h>
24 #include <sys/uio.h>
25 #include <sys/un.h>
26 #include <time.h>
27 #include <unistd.h>
28
29 #define LOG_LEN 3
30 #define ERROR_FD 2
31
32 const int SOCKET_TYPE = SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC;
33 const int INVALID_SOCKET = -1;
34 const struct sockaddr_un SOCKET_ADDR = {AF_UNIX, SOCKET_FILE_DIR INPUT_SOCKET_NAME};
35
SendMessage(HilogMsg * header,const char * tag,uint16_t tagLen,const char * fmt,uint16_t fmtLen)36 static int SendMessage(HilogMsg *header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen)
37 {
38 // The hilogbase interface cannot has mutex, so need to re-open and connect to the socketof the hilogd
39 // server each time you write logs. Althougth there is some overhead, you can only do this.
40 int socketFd = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCKET_TYPE, 0));
41 if (socketFd < 0) {
42 dprintf(ERROR_FD, "HiLogBase: Can't create socket! Errno: %d\n", errno);
43 return socketFd;
44 }
45
46 long int result =
47 TEMP_FAILURE_RETRY(connect(socketFd, (const struct sockaddr *)(&SOCKET_ADDR), sizeof(SOCKET_ADDR)));
48 if (result < 0) {
49 dprintf(ERROR_FD, "HiLogBase: Can't connect to server. Errno: %d\n", errno);
50 if (socketFd >= 0) {
51 close(socketFd);
52 }
53 return result;
54 }
55
56 struct timespec ts = {0};
57 (void)clock_gettime(CLOCK_REALTIME, &ts);
58 struct timespec ts_mono = {0};
59 (void)clock_gettime(CLOCK_MONOTONIC, &ts_mono);
60 header->tv_sec = (uint32_t)(ts.tv_sec);
61 header->tv_nsec = (uint32_t)(ts.tv_nsec);
62 header->mono_sec = (uint32_t)(ts_mono.tv_sec);
63 header->len = sizeof(HilogMsg) + tagLen + fmtLen;
64 header->tag_len = tagLen;
65
66 struct iovec vec[LOG_LEN] = {0};
67 vec[0].iov_base = header; // 0 : index of hos log header
68 vec[0].iov_len = sizeof(HilogMsg); // 0 : index of hos log header
69 vec[1].iov_base = (void *)((char *)(tag)); // 1 : index of log tag
70 vec[1].iov_len = tagLen; // 1 : index of log tag
71 vec[2].iov_base = (void *)((char *)(fmt)); // 2 : index of log content
72 vec[2].iov_len = fmtLen; // 2 : index of log content
73 int ret = TEMP_FAILURE_RETRY(writev(socketFd, vec, LOG_LEN));
74 if (socketFd >= 0) {
75 close(socketFd);
76 }
77 return ret;
78 }
79
HiLogBasePrintArgs(const LogType type,const LogLevel level,const unsigned int domain,const char * tag,const char * fmt,va_list ap)80 int HiLogBasePrintArgs(
81 const LogType type, const LogLevel level, const unsigned int domain, const char *tag, const char *fmt, va_list ap)
82 {
83 char buf[MAX_LOG_LEN] = {0};
84
85 vsnprintfp_s(buf, MAX_LOG_LEN, MAX_LOG_LEN - 1, true, fmt, ap);
86
87 size_t tagLen = strnlen(tag, MAX_TAG_LEN - 1);
88 size_t logLen = strnlen(buf, MAX_LOG_LEN - 1);
89 HilogMsg header = {0};
90 header.type = type;
91 header.level = level;
92 #ifndef __RECV_MSG_WITH_UCRED_
93 header.pid = getpid();
94 #endif
95 header.tid = (uint32_t)(gettid());
96 header.domain = domain;
97
98 return SendMessage(&header, tag, tagLen + 1, buf, logLen + 1);
99 }
100
HiLogBasePrint(LogType type,LogLevel level,unsigned int domain,const char * tag,const char * fmt,...)101 int HiLogBasePrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...)
102 {
103 if (!HiLogBaseIsLoggable(domain, tag, level)) {
104 return -1;
105 }
106
107 int ret;
108 va_list ap;
109 va_start(ap, fmt);
110 ret = HiLogBasePrintArgs(type, level, domain, tag, fmt, ap);
111 va_end(ap);
112 return ret;
113 }
114
HiLogBaseIsLoggable(unsigned int domain,const char * tag,LogLevel level)115 bool HiLogBaseIsLoggable(unsigned int domain, const char *tag, LogLevel level)
116 {
117 if ((level <= LOG_LEVEL_MIN) || (level >= LOG_LEVEL_MAX) || tag == NULL) {
118 return false;
119 }
120 return true;
121 }