1 /*
2 * Copyright (c) 2020 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 <errno.h>
17 #include <fcntl.h>
18 #include <securec.h>
19 #include <string.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <time.h>
23 #include <unistd.h>
24
25 #include "hilog_command.h"
26
27 #define HILOG_LOGBUFFER 2048
28 #ifndef HILOG_DIR
29 #define HILOG_DIR "/storage/data/log"
30 #endif
31 #define HILOG_PATH1 HILOG_DIR "/hilog1.txt"
32 #define HILOG_PATH2 HILOG_DIR "/hilog2.txt"
33
34 #undef LOG_TAG
35 #define LOG_TAG "apphilogcat"
36
37 static int file1Size = 0;
38 static int file2Size = 0;
39
40 int FlushAndSync(FILE *fp);
41
FileSize(const char * filename)42 static int FileSize(const char *filename)
43 {
44 FILE *fp = fopen(filename, "r");
45 if (!fp) {
46 return -1;
47 }
48
49 int size = 0;
50 int ret = fseek(fp, 0L, SEEK_END);
51 if (ret == 0) {
52 size = ftell(fp);
53 }
54 fclose(fp);
55
56 return size;
57 }
58
FileClear(FILE ** fp,const char * filename)59 static FILE *FileClear(FILE **fp, const char *filename)
60 {
61 if (*fp != NULL) {
62 fclose(*fp);
63 }
64 *fp = fopen(filename, "w");
65 if (*fp == NULL) {
66 return NULL;
67 }
68 printf("write file switch %s\n", filename);
69 return *fp;
70 }
71
SelectWriteFile(FILE ** fp1,FILE * fp2)72 FILE *SelectWriteFile(FILE **fp1, FILE *fp2)
73 {
74 file1Size = FileSize(HILOG_PATH1);
75 file2Size = FileSize(HILOG_PATH2);
76 if (file1Size < HILOG_MAX_FILELEN) {
77 return *fp1;
78 } else if (file2Size < HILOG_MAX_FILELEN) {
79 return fp2;
80 } else { // clear file1 write file 1
81 file1Size = 0;
82 return FileClear(fp1, HILOG_PATH1);
83 }
84 }
85
SwitchWriteFile(FILE ** fp1,FILE ** fp2,FILE * curFp)86 FILE *SwitchWriteFile(FILE **fp1, FILE **fp2, FILE *curFp)
87 {
88 // select file, if file1 is full, record file2, file2 is full, record file1
89 if (file1Size < HILOG_MAX_FILELEN) {
90 return *fp1;
91 } else if (file2Size < HILOG_MAX_FILELEN) {
92 return *fp2;
93 } else if (curFp == *fp2) { // clear file1 write file 1
94 FlushAndSync(*fp2);
95 file1Size = 0;
96 return FileClear(fp1, HILOG_PATH1);
97 } else {
98 FlushAndSync(*fp1);
99 file2Size = 0;
100 return FileClear(fp2, HILOG_PATH2);
101 }
102 }
103
FlushAndSync(FILE * fp)104 int FlushAndSync(FILE *fp)
105 {
106 if (fp == NULL) {
107 return 0;
108 }
109 if (fflush(fp) != 0) {
110 return -1;
111 }
112 int fd = fileno(fp);
113 if (fsync(fd) != 0) {
114 return -1;
115 }
116 return 0;
117 }
118
NeedFlush(const char * buf)119 bool NeedFlush(const char *buf)
120 {
121 #define FLUSH_LOG_ARG_0 0
122 #define FLUSH_LOG_ARG_1 1
123 #define FLUSH_LOG_FLAG 0x07
124 if (buf[FLUSH_LOG_ARG_0] == FLUSH_LOG_FLAG && buf[FLUSH_LOG_ARG_1] == FLUSH_LOG_FLAG) {
125 return true;
126 }
127 return false;
128 }
129
FileClose(FILE * file)130 static void FileClose(FILE *file)
131 {
132 if (file != NULL) {
133 fclose(file);
134 }
135 }
136
main(int argc,char * argv[])137 int main(int argc, char *argv[])
138 {
139 #define HILOG_UMASK 0027
140 int fd = -1;
141 int ret = -1;
142 FILE *fpWrite = NULL;
143 bool printFlag = true;
144
145 if (argc > 1) {
146 ret = HilogCmdProc(LOG_TAG, argc, argv);
147 if (ret == -1) {
148 return 0;
149 }
150 }
151
152 fd = open(HILOG_DRIVER, O_RDONLY | O_CLOEXEC);
153 if (fd < 0) {
154 printf("hilog fd failed %s\n", strerror(errno));
155 return 0;
156 }
157
158 umask(HILOG_UMASK);
159 FILE *fp1 = fopen(HILOG_PATH1, "at");
160 if (fp1 == NULL) {
161 printf("open err fp1 %s\n", strerror(errno));
162 close(fd);
163 return 0;
164 }
165
166 FILE *fp2 = fopen(HILOG_PATH2, "at");
167 if (fp2 == NULL) {
168 printf("open err fp2 %s\n", strerror(errno));
169 FileClose(fp1);
170 close(fd);
171 return 0;
172 }
173 // First select
174 fpWrite = SelectWriteFile(&fp1, fp2);
175 if (fpWrite == NULL) {
176 printf("SelectWriteFile open err\n");
177 close(fd);
178 FileClose(fp1);
179 FileClose(fp2);
180 return 0;
181 }
182 char *buf = malloc(HILOG_LOGBUFFER + 1);
183 if (buf == NULL) {
184 close(fd);
185 FileClose(fp1);
186 FileClose(fp2);
187 return 0;
188 }
189 while (1) {
190 (void)memset_s(buf, HILOG_LOGBUFFER + 1, 0, HILOG_LOGBUFFER + 1);
191 ret = read(fd, buf, HILOG_LOGBUFFER);
192 if (ret < 0 || ret < sizeof(struct HiLogEntry)) {
193 continue;
194 }
195 struct HiLogEntry *head = (struct HiLogEntry *)buf;
196
197 if (NeedFlush(head->msg)) {
198 if (FlushAndSync(fpWrite) != 0) {
199 printf("flush and sync file err\n");
200 }
201 continue;
202 }
203
204 time_t rawtime;
205 struct tm *info = NULL;
206 struct tm nowTime = {0};
207 unsigned int sec = head->sec;
208 rawtime = (time_t)sec;
209 /* Get local time */
210 info = localtime_r(&rawtime, &nowTime);
211
212 printFlag = FilterLevelLog(g_hiviewConfig.level, *(head->msg));
213 if (!printFlag) {
214 continue;
215 }
216 #define MODULE_OFFSET 2
217 printFlag = FilterModuleLog(g_hiviewConfig.logOutputModule, (head->msg) + MODULE_OFFSET);
218 if (!printFlag) {
219 continue;
220 }
221
222 if (info == NULL) {
223 continue;
224 }
225 buf[HILOG_LOGBUFFER - 1] = '\0';
226
227 if (g_hiviewConfig.silenceMod == SILENT_MODE_OFF) {
228 printf("%02d-%02d %02d:%02d:%02d.%03d %d %d %s\n", info->tm_mon + 1, info->tm_mday, info->tm_hour,
229 info->tm_min, info->tm_sec, head->nsec / NANOSEC_PER_MIRCOSEC, head->pid, head->taskId, head->msg);
230 }
231
232 ret =
233 fprintf(fpWrite, "%02d-%02d %02d:%02d:%02d.%03d %d %d %s\n", info->tm_mon + 1, info->tm_mday, info->tm_hour,
234 info->tm_min, info->tm_sec, head->nsec / NANOSEC_PER_MIRCOSEC, head->pid, head->taskId, head->msg);
235 if (ret < 0) {
236 printf("[FATAL]File can't write fpWrite %s\n", strerror(errno));
237 free(buf);
238 close(fd);
239 FileClose(fp1);
240 FileClose(fp2);
241 return 0;
242 }
243 if (fpWrite == fp1) {
244 file1Size += ret;
245 } else if (fpWrite == fp2) {
246 file2Size += ret;
247 }
248 // select file, if file1 is full, record file2, file2 is full, record file1
249 fpWrite = SwitchWriteFile(&fp1, &fp2, fpWrite);
250 if (fpWrite == NULL) {
251 printf("[FATAL]SwitchWriteFile failed\n");
252 free(buf);
253 close(fd);
254 FileClose(fp1);
255 FileClose(fp2);
256 return 0;
257 }
258 }
259 free(buf);
260 close(fd);
261 FileClose(fp1);
262 FileClose(fp2);
263 return 0;
264 }
265