blob: a90766200cfc2a7e33e8bcdd050ad44d5f3e8eef [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001#include <stdio.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <sys/socket.h>
5#include <netinet/in.h>
6#include <netdb.h>
7#include <arpa/inet.h>
8#include <fcntl.h>
9#include <time.h>
10#include <unistd.h>
11#include <errno.h>
12#include "log_config.h"
13
14#define ALOG_DEV "/dev/log_radio"
xf.li43643772024-03-04 19:39:53 -080015#define LOG_CONFIG_LEN 50
liubin281ac462023-07-19 14:22:54 +080016
l.yang67782e62024-11-05 01:28:10 -080017#define RADIOLOG_BUFF_SIZE (4*1024)
18#define MAX_BUFFER_SIZE (8*1024)
19
liubin281ac462023-07-19 14:22:54 +080020typedef enum android_LogPriority {
21 ANDROID_LOG_UNKNOWN = 0,
22 ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
23 ANDROID_LOG_VERBOSE,
24 ANDROID_LOG_DEBUG,
25 ANDROID_LOG_INFO,
26 ANDROID_LOG_WARN,
27 ANDROID_LOG_ERROR,
28 ANDROID_LOG_FATAL,
29 ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
30} android_LogPriority;
31
32typedef struct AndroidLogEntry_t {
33 time_t tv_sec;
34 long tv_nsec;
35 android_LogPriority priority;
36 int32_t pid;
37 int32_t tid;
38 const char * tag;
39 size_t messageLen;
40 const char * message;
41} AndroidLogEntry;
42
xf.li43643772024-03-04 19:39:53 -080043//static const char *log_file, *log_ip, *log_port, *log_prefix, *pid_file, *hostname;
44static char log_file[LOG_CONFIG_LEN], log_ip[LOG_CONFIG_LEN], log_port[LOG_CONFIG_LEN], log_prefix[LOG_CONFIG_LEN], pid_file[LOG_CONFIG_LEN], hostname[LOG_CONFIG_LEN];
liubin281ac462023-07-19 14:22:54 +080045static int log_size = 1 * 1024 * 1024;
46
47static log_config_entry *config = NULL;
48static char tmp_log[48] = {0};
49
l.yangb7972c72024-10-15 22:34:51 -070050static int fd_radio = 0;
51
l.yang67782e62024-11-05 01:28:10 -080052
liubin281ac462023-07-19 14:22:54 +080053void hex_print(char* buf, int len)
54{
55 int i;
56
57 for (i = 0; i < len; i++) {
58 printf("%x ", buf[i]);
59 }
60}
61
62static char filterPriToChar(android_LogPriority pri)
63{
64 switch (pri) {
65 case ANDROID_LOG_VERBOSE:
66 return 'V';
67 case ANDROID_LOG_DEBUG:
68 return 'D';
69 case ANDROID_LOG_INFO:
70 return 'I';
71 case ANDROID_LOG_WARN:
72 return 'W';
73 case ANDROID_LOG_ERROR:
74 return 'E';
75 case ANDROID_LOG_FATAL:
76 return 'F';
77 case ANDROID_LOG_SILENT:
78 return 'S';
79
80 case ANDROID_LOG_DEFAULT:
81 case ANDROID_LOG_UNKNOWN:
82 default:
83 return '?';
84 }
85}
86
87static android_LogPriority filterCharToPri(char c)
88{
89 switch (c) {
90 case 'v':
91 return ANDROID_LOG_VERBOSE;
92 case 'd':
93 return ANDROID_LOG_DEBUG;
94 case 'i':
95 return ANDROID_LOG_INFO;
96 case 'w':
97 return ANDROID_LOG_WARN;
98 case 'e':
99 return ANDROID_LOG_ERROR;
100 case 'f':
101 return ANDROID_LOG_FATAL;
102 case 's':
103 return ANDROID_LOG_SILENT;
104 case '*':
105 default:
106 return ANDROID_LOG_VERBOSE;
107 }
108}
109
110int fileter_log(int pri, char *tag, struct filter_list_t *filter)
111{
112 struct filter_list_t *_filter = filter;
113
114 while(_filter)
115 {
116 int p = filterCharToPri(_filter->priority);
117 if(_filter->tag)
118 {
119 int len = strlen(_filter->tag);
120 // tag and priority
121 if(0 == memcmp(_filter->tag, tag, len) && ((pri > p) || (pri == p)))
122 return 0;
123 }else{ // have no tag
124 if(pri < p)
125 return -1;
126 else
127 return 0;
128 }
129 _filter = _filter->next;
130 }
131
132 return -1;
133}
134
135int alog_process(char* data, int len, AndroidLogEntry *entry)
136{
137 int i, n = 0;
138 int tmp_len;
139
140 for (i = 0; i < len;) {
141 if (data[i] == '\0') {
142 i += 1;
143 } else {
144 switch (n) {
145 case 0: {
146 // printf("%d - %d: %x\n", i, tmp_len, data[i]);
147 i++;
148 break;
149 }
150 case 1: {
151 int* pid = (int*)&data[i];
152 entry->pid = *pid;
153 // printf("%d pid: %d\n", i, entry->pid);
154 i += 4;
155 break;
156 }
157 case 2: {
158 int* tid = (int*)&data[i];
159 entry->tid = *tid;
160 // printf("%d tid: %d\n", i, entry->tid);
161 i += 4;
162 break;
163 }
164 case 3: {
165 // printf("%d - %d: %x %x %x %x\n", i, tmp_len, data[i], data[i + 1], data[i + 2], data[i + 3]);
166 time_t* _t = (time_t*)&data[i];
167 entry->tv_sec = *_t;
168 i += 8;
169 break;
170 }
171 case 4: {
172 entry->priority = data[i];
173 entry->tag = &data[i + 1];
174 i += strlen(&data[i]);
175 break;
176 }
177 //* format: <priority:1><tag:N>\0<message:N>\0
178 case 5: {
179 entry->message = &data[i];
180 entry->messageLen = strlen(&data[i]);
181 i += entry->messageLen;
182 break;
183 }
184 default:
185 printf("process error \n");
186 break;
187 }
188 n++;
189 }
190 }
191 return 0;
192}
193
194int android_log_printLogLine(
liubin281ac462023-07-19 14:22:54 +0800195 struct file_list_t *_file_list,
196 const AndroidLogEntry *entry)
197{
198 char priChar;
199 char timeBuf[32];
l.yang67782e62024-11-05 01:28:10 -0800200 char defaultBuffer[512] = {0};
liubin281ac462023-07-19 14:22:54 +0800201 size_t totalLen;
xf.li01e39822024-10-30 16:00:32 +0800202 int index = 0;
203 int len = 0;
l.yangb7972c72024-10-15 22:34:51 -0700204 struct stat s;
l.yang67782e62024-11-05 01:28:10 -0800205
206
207 static char buffer[MAX_BUFFER_SIZE] = {0};
208 static int buffer_index = 0;
l.yangb7972c72024-10-15 22:34:51 -0700209
210 if(access(tmp_log, W_OK) != 0)
211 {
212 fd_radio = open(tmp_log, O_CREAT | O_WRONLY| O_APPEND, 0600);
213 if (fd_radio < 0)
214 {
215 fprintf(stderr, "failed to open %s: %s\n", tmp_log, strerror(errno));
216 exit(-1);
liubin281ac462023-07-19 14:22:54 +0800217 }
l.yangb7972c72024-10-15 22:34:51 -0700218
219 }
l.yang67782e62024-11-05 01:28:10 -0800220
221
l.yangb7972c72024-10-15 22:34:51 -0700222 if (log_size && (!stat(tmp_log, &s)) && (s.st_size > log_size))
223 {
224 fd_radio = get_rotate_file(fd_radio, log_file, _file_list);
225 if (fd_radio < 0)
226 {
227 fprintf(stderr, "failed to open %s: %s\n", log_file, strerror(errno));
228 exit(-1);
229 }
l.yang67782e62024-11-05 01:28:10 -0800230
l.yangb7972c72024-10-15 22:34:51 -0700231 }
liubin281ac462023-07-19 14:22:54 +0800232
233 if(fileter_log(entry->priority, entry->tag, config->filter_list))
234 {
235 // printf("%s %d: fileter pri:%d tag:%s!\n", __FUNCTION__, __LINE__, entry->priority, entry->tag);
236 return -1;
237 }
238
239 priChar = filterPriToChar(entry->priority);
240 struct tm* ptm = localtime(&entry->tv_sec);
241 strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
242
243 totalLen = snprintf(defaultBuffer, sizeof(defaultBuffer),
244 "%s %c/%s (%d): %s\n", timeBuf, priChar, entry->tag, entry->pid, entry->message);
xf.li01e39822024-10-30 16:00:32 +0800245
246 len = strlen(defaultBuffer);
247 if(access("/etc/syslog_encrypt_flag", F_OK) == 0)
248 {
249 for(index = 0; index < len; index++)
250 {
251 defaultBuffer[index] ^= 1;
252 }
253 }
liubin281ac462023-07-19 14:22:54 +0800254
l.yang67782e62024-11-05 01:28:10 -0800255
256 if(buffer_index >= RADIOLOG_BUFF_SIZE)
257 {
258 // Flush the buffer if it's full
259 if (write(fd_radio, buffer, buffer_index) < 0)
260 {
261 perror("write error");
262 return -1;
263 }
264 buffer_index = 0; // Reset buffer index after flushing
265 }
266
267 if(totalLen < RADIOLOG_BUFF_SIZE)
268 {
269 //copy buf to buffer
270 memcpy(buffer + buffer_index, defaultBuffer, totalLen);
271 buffer_index += totalLen;
272 }
273 else
274 {
275 write(fd_radio, defaultBuffer, totalLen);
276 }
277
278
279 return 0;
liubin281ac462023-07-19 14:22:54 +0800280}
281
282void* alog_thread(void* argv)
283{
284 int dev_fd, ret;
285 int log_fd;
286 AndroidLogEntry entry;
287 char buf[512] = {0};
288 static struct file_list_t file_list;
289 config = (log_config_entry *)argv;
290
291 pthread_detach(pthread_self());
292 if (NULL == argv)
293 return NULL;
294
295 dev_fd = open(ALOG_DEV, O_RDONLY, 0600);
296 if (dev_fd < 0) {
297 fprintf(stderr, "failed to open %s: %s\n", ALOG_DEV, strerror(errno));
298 exit(-1);
299 }
300
301 memset(&file_list, 0, sizeof(struct file_list_t));
302 file_list.total = config->rotate_file_count;
xf.li43643772024-03-04 19:39:53 -0800303 //log_file = config->out_path;
304 memset(log_file, 0, sizeof(log_file));
305 memset(log_ip, 0, sizeof(log_ip));
306 memset(log_port, 0, sizeof(log_port));
307 memset(log_prefix, 0, sizeof(log_prefix));
308 memset(pid_file, 0, sizeof(pid_file));
309 memset(hostname, 0, sizeof(hostname));
310 if(config->out_path != NULL)
311 {
312 strncpy(log_file, config->out_path, LOG_CONFIG_LEN - 1);
313 }
liubin281ac462023-07-19 14:22:54 +0800314
l.yangb7972c72024-10-15 22:34:51 -0700315 if (config->ip && config->port)
316 {
liubin281ac462023-07-19 14:22:54 +0800317 int port = atoi(config->port);
318 printf("%s %d : %s:%s\n", __FUNCTION__, __LINE__, config->ip, config->port);
319 log_fd = tcp_connect(config->ip, port);
l.yangb7972c72024-10-15 22:34:51 -0700320 }
321 else if (strlen(log_file) > 0)
322 {
323 //sprintf(tmp_log, "/tmp/log%s", strstr_tail(log_file, "/"));
324
325 snprintf(tmp_log,sizeof(tmp_log), "%s", log_file);
liubin281ac462023-07-19 14:22:54 +0800326 // 先将文件保存到 /tmp/log/ 目录下,后面到达 rotate_file_size 后,转移到out_path
l.yangb7972c72024-10-15 22:34:51 -0700327
328 }
329 else
330 {
liubin281ac462023-07-19 14:22:54 +0800331 log_fd = STDOUT_FILENO;
332 }
333 if(config->rotate_file_size)
l.yangb7972c72024-10-15 22:34:51 -0700334 {
liubin281ac462023-07-19 14:22:54 +0800335 log_size = config->rotate_file_size;
l.yangb7972c72024-10-15 22:34:51 -0700336 }
liubin281ac462023-07-19 14:22:54 +0800337 printf("android log start...\n");
l.yangb7972c72024-10-15 22:34:51 -0700338 while (1)
339 {
liubin281ac462023-07-19 14:22:54 +0800340 ret = read(dev_fd, buf, sizeof(buf));
l.yangb7972c72024-10-15 22:34:51 -0700341 if (ret < 0)
342 {
liubin281ac462023-07-19 14:22:54 +0800343 printf("read error\n");
344 break;
345 }
346 alog_process(buf, ret, &entry);
l.yangb7972c72024-10-15 22:34:51 -0700347 android_log_printLogLine(&file_list, &entry);
liubin281ac462023-07-19 14:22:54 +0800348 memset(buf, 0, sizeof(buf));
349 }
350 close(dev_fd);
l.yangb7972c72024-10-15 22:34:51 -0700351
liubin281ac462023-07-19 14:22:54 +0800352 printf("%s exit \n", __FUNCTION__);
353 pthread_exit(NULL);
354 return NULL;
355}