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