xref: /base/hiviewdfx/hiview_lite/hiview_file.c (revision 6f2c2def)
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 "hiview_config.h"
17#include "hiview_def.h"
18#include "hiview_event.h"
19#include "hiview_file.h"
20#include "hiview_log.h"
21#include "hiview_util.h"
22#include "ohos_types.h"
23#include "securec.h"
24
25static uint32 GetDefineFileVersion(uint8 type)
26{
27    switch (type) {
28        case HIVIEW_UE_EVENT_FILE:
29            return HIVIEW_UE_EVENT_VER;
30        case HIVIEW_STAT_EVENT_FILE:
31            return HIVIEW_STATIC_EVENT_VER;
32        case HIVIEW_FAULT_EVENT_FILE:
33            return HIVIEW_FAULT_EVENT_VER;
34        default:
35            // non-event file
36            return 0;
37    }
38}
39
40boolean InitHiviewFile(HiviewFile *fp, HiviewFileType type, uint32 size)
41{
42    if (fp == NULL || fp->path == NULL) {
43        return FALSE;
44    }
45
46    fp->fhandle = HIVIEW_FileOpen(fp->path);
47    if (fp->fhandle < 0) {
48        int32 errnoRecord = (int32)errno;
49        uint16 hieventID = 1;
50        HiEvent *hievent = HIEVENT_CREATE(HIEVENT_FAULT, hieventID, 2); // 2 params
51        HIEVENT_PUT_INT_VALUE(hievent, 0, (int32)type);
52        HIEVENT_PUT_INT_VALUE(hievent, 1, errnoRecord);
53        HIEVENT_REPORT(hievent);
54        return FALSE;
55    }
56
57    HiviewFileHeader *pHeader = &(fp->header);
58    FileHeaderCommon *pCommon = &(pHeader->common);
59    pCommon->type = (uint8)type;
60    pHeader->size = size + sizeof(HiviewFileHeader);
61    fp->configSize = size;
62    // Create file for the first time
63    if (ReadFileHeader(fp) == FALSE) {
64        switch (pCommon->type) {
65            case HIVIEW_LOG_TEXT_FILE:
66                pCommon->prefix = HIVIEW_FILE_HEADER_PREFIX_TEXT;
67                break;
68            case HIVIEW_LOG_BIN_FILE:
69                pCommon->prefix = HIVIEW_FILE_HEADER_PREFIX_LOG;
70                break;
71            case HIVIEW_FAULT_EVENT_FILE:
72            case HIVIEW_UE_EVENT_FILE:
73            case HIVIEW_STAT_EVENT_FILE:
74                pCommon->prefix = HIVIEW_FILE_HEADER_PREFIX_EVENT;
75                break;
76            default:
77                break;
78        }
79        pCommon->codeMainVersion = HIVIEW_FILE_HEADER_MAIN_VERSION;
80        pCommon->codeSubVersion = HIVIEW_FILE_HEADER_SUB_VERSION;
81        pCommon->defineFileVersion = GetDefineFileVersion(pCommon->type);
82        pHeader->createTime = (uint32)(HIVIEW_GetCurrentTime() / MS_PER_SECOND);
83        pHeader->rCursor = sizeof(HiviewFileHeader);
84        pHeader->wCursor = sizeof(HiviewFileHeader);
85        if (WriteFileHeader(fp) == FALSE) {
86            return FALSE;
87        }
88    } else {
89        // Version number may change after system upgrade
90        pCommon->codeMainVersion = HIVIEW_FILE_HEADER_MAIN_VERSION;
91        pCommon->codeSubVersion = HIVIEW_FILE_HEADER_SUB_VERSION;
92        pCommon->defineFileVersion = GetDefineFileVersion(pCommon->type);
93    }
94    HILOG_INFO(HILOG_MODULE_HIVIEW, "InitHiviewFile for type %d success", (int32)type);
95    return TRUE;
96}
97
98boolean WriteFileHeader(HiviewFile *fp)
99{
100    if (fp == NULL || fp->fhandle < 0) {
101        return FALSE;
102    }
103
104    int32 ret;
105    if (HIVIEW_FileSeek(fp->fhandle, 0, HIVIEW_SEEK_SET) >= 0) {
106        HiviewFileHeader tmpHeader = fp->header;
107#if LITTLE_ENDIAN_SYSTEM
108        tmpHeader.common.prefix = Change32Endian(tmpHeader.common.prefix);
109        tmpHeader.common.defineFileVersion = Change32Endian(tmpHeader.common.defineFileVersion);
110        tmpHeader.createTime = Change32Endian(tmpHeader.createTime);
111#endif
112        ret = HIVIEW_FileWrite(fp->fhandle, (uint8 *)&(tmpHeader), sizeof(HiviewFileHeader));
113        if (ret == sizeof(HiviewFileHeader)) {
114            return TRUE;
115        }
116    }
117
118    return FALSE;
119}
120
121boolean ReadFileHeader(HiviewFile *fp)
122{
123    HiviewFileHeader h = { 0 };
124
125    if (fp == NULL || fp->fhandle < 0) {
126        return FALSE;
127    }
128
129    int32 ret;
130    if (HIVIEW_FileSeek(fp->fhandle, 0, HIVIEW_SEEK_SET) < 0) {
131        return FALSE;
132    }
133    ret = HIVIEW_FileRead(fp->fhandle, (uint8 *)&h, sizeof(HiviewFileHeader));
134#if LITTLE_ENDIAN_SYSTEM
135    h.common.prefix = Change32Endian(h.common.prefix);
136    h.common.defineFileVersion = Change32Endian(h.common.defineFileVersion);
137    h.createTime = Change32Endian(h.createTime);
138#endif
139    h.wCursor = HIVIEW_FileSize(fp->fhandle);
140    h.rCursor = sizeof(HiviewFileHeader);
141    if ((ret == sizeof(HiviewFileHeader)) &&
142        ((h.common.prefix & 0xFFFFFF00) == HIVIEW_FILE_HEADER_PREFIX_MASK) &&
143        (h.wCursor >= sizeof(HiviewFileHeader))) {
144        (void)memcpy_s(&(fp->header), sizeof(HiviewFileHeader), (void *)&h, sizeof(HiviewFileHeader));
145        return TRUE;
146    } else {
147        return FALSE;
148    }
149}
150
151int32 WriteToFile(HiviewFile *fp, const uint8 *data, uint32 len)
152{
153    if (fp == NULL || fp->fhandle < 0 || len == 0) {
154        return 0;
155    }
156    int32 wLen = 0;
157    HiviewFileHeader *h = &(fp->header);
158    // overflow
159    if (h->wCursor + len > h->size) {
160        ProcFile(fp, fp->outPath, HIVIEW_FILE_RENAME);
161        if (fp->pFunc != NULL) {
162            fp->pFunc(fp->outPath, h->common.type, HIVIEW_FILE_FULL);
163        }
164    }
165    if (HIVIEW_FileSeek(fp->fhandle, h->wCursor, HIVIEW_SEEK_SET) < 0) {
166        return 0;
167    }
168    if ((int32)len == HIVIEW_FileWrite(fp->fhandle, data, len)) {
169        h->wCursor += len;
170        wLen += len;
171    }
172    return wLen;
173}
174
175int32 ReadFromFile(HiviewFile *fp, uint8 *data, uint32 readLen)
176{
177    if (fp == NULL || data == NULL || fp->fhandle < 0 || readLen == 0) {
178        return 0;
179    }
180
181    HiviewFileHeader* h = &(fp->header);
182    uint32 wCursor = h->wCursor;
183    uint32 rCursor = h->rCursor;
184    if (wCursor < readLen) {
185        return 0;
186    }
187    int32 rLen = (readLen <= (wCursor - rCursor)) ? readLen : (wCursor - rCursor);
188    if (HIVIEW_FileSeek(fp->fhandle, rCursor, HIVIEW_SEEK_SET) < 0) {
189        return 0;
190    }
191    if ((int32)rLen == HIVIEW_FileRead(fp->fhandle, data, rLen)) {
192        h->rCursor += rLen;
193    } else {
194        rLen = 0;
195    }
196    return rLen;
197}
198
199uint32 GetFileUsedSize(HiviewFile *fp)
200{
201    if (fp == NULL || fp->fhandle < 0) {
202        return 0;
203    }
204    return fp->header.wCursor;
205}
206
207uint32 GetFileFreeSize(HiviewFile *fp)
208{
209    if (fp == NULL || fp->fhandle < 0) {
210        return 0;
211    }
212
213    return (fp->header.size - fp->header.wCursor);
214}
215
216int32 CloseHiviewFile(HiviewFile *fp)
217{
218    if (fp != NULL && fp->fhandle > 0) {
219        int32 ret = HIVIEW_FileClose(fp->fhandle);
220        fp->fhandle = -1;
221        UnRegisterFileWatcher(fp, NULL);
222        return ret;
223    }
224    return -1;
225}
226
227int8 ProcFile(HiviewFile *fp, const char *dest, FileProcMode mode)
228{
229    if (fp == NULL || fp->fhandle < 0) {
230        return -1;
231    }
232
233    if (HIVIEW_MutexLockOrWait(fp->mutex, OUT_PATH_WAIT_TIMEOUT) != 0) {
234        HIVIEW_UartPrint("Procfile failed, get lock fail");
235        return -1;
236    }
237    switch (mode) {
238        case HIVIEW_FILE_COPY: {
239            HIVIEW_FileClose(fp->fhandle);
240            int32 ret = HIVIEW_FileCopy(fp->path, dest);
241            fp->fhandle = HIVIEW_FileOpen(fp->path);
242            if (ret != 0 || fp->fhandle < 0) {
243                int32 errnoRecord = (int32)errno;
244                HIVIEW_MutexUnlock(fp->mutex);
245                uint16 hieventID = 1;
246                HiEvent *hievent = HIEVENT_CREATE(HIEVENT_FAULT, hieventID, 2); // 2 params
247                HIEVENT_PUT_INT_VALUE(hievent, 0, (int32)fp->header.common.type);
248                HIEVENT_PUT_INT_VALUE(hievent, 1, errnoRecord);
249                HIEVENT_REPORT(hievent);
250                HIVIEW_UartPrint("Procfile failed, type : HIVIEW_FILE_COPY");
251                return -1;
252            }
253            break;
254        }
255        case HIVIEW_FILE_RENAME: {
256            HIVIEW_FileClose(fp->fhandle);
257            uint8 type = fp->header.common.type;
258            uint32 size = fp->configSize;
259            int32 ret = HIVIEW_FileMove(fp->path, dest);
260            if (InitHiviewFile(fp, (HiviewFileType)type, size) == FALSE || ret != 0) {
261                HIVIEW_MutexUnlock(fp->mutex);
262                HIVIEW_UartPrint("Procfile failed, type : HIVIEW_FILE_RENAME");
263                return -1;
264            }
265            break;
266        }
267        default:
268            HIVIEW_MutexUnlock(fp->mutex);
269            HIVIEW_UartPrint("Procfile failed, type : Unknown type");
270            return -1;
271    }
272    HIVIEW_MutexUnlock(fp->mutex);
273    return 0;
274}
275
276int IsValidPath(const char *path)
277{
278    if (strcmp(path, HIVIEW_FILE_PATH_LOG) == 0 ||
279        strcmp(path, HIVIEW_FILE_PATH_UE_EVENT) == 0 ||
280        strcmp(path, HIVIEW_FILE_PATH_FAULT_EVENT) == 0 ||
281        strcmp(path, HIVIEW_FILE_PATH_STAT_EVENT) == 0 ||
282        strcmp(path, HIVIEW_FILE_OUT_PATH_LOG) == 0 ||
283        strcmp(path, HIVIEW_FILE_OUT_PATH_UE_EVENT) == 0 ||
284        strcmp(path, HIVIEW_FILE_OUT_PATH_FAULT_EVENT) == 0 ||
285        strcmp(path, HIVIEW_FILE_OUT_PATH_STAT_EVENT) == 0) {
286            return -1;
287    }
288    return 0;
289}
290
291void RegisterFileWatcher(HiviewFile *fp, FileProc func, const char *path)
292{
293    if (fp == NULL || func == NULL) {
294        return;
295    }
296    fp->pFunc = func;
297    if (path == NULL || IsValidPath(path) != 0) {
298        return;
299    }
300
301    int len = strlen(path) + 1;
302    char* tmp = (char*)HIVIEW_MemAlloc(MEM_POOL_HIVIEW_ID, len);
303    if (tmp == NULL) {
304        return;
305    }
306    if (strcpy_s(tmp, len, path) != EOK) {
307        HIVIEW_MemFree(MEM_POOL_HIVIEW_ID, tmp);
308        return;
309    }
310    fp->outPath = tmp;
311}
312
313void UnRegisterFileWatcher(HiviewFile *fp, FileProc func)
314{
315    (void)func;
316    fp->pFunc = NULL;
317    if (IsValidPath(fp->outPath) == 0) {
318        HIVIEW_MemFree(MEM_POOL_HIVIEW_ID, fp->outPath);
319    }
320    switch (fp->header.common.type) {
321        case HIVIEW_FAULT_EVENT_FILE:
322            fp->outPath = HIVIEW_FILE_OUT_PATH_FAULT_EVENT;
323            break;
324        case HIVIEW_UE_EVENT_FILE:
325            fp->outPath = HIVIEW_FILE_OUT_PATH_UE_EVENT;
326            break;
327        case HIVIEW_STAT_EVENT_FILE:
328            fp->outPath = HIVIEW_FILE_OUT_PATH_STAT_EVENT;
329            break;
330        case HIVIEW_LOG_TEXT_FILE:
331        case HIVIEW_LOG_BIN_FILE:
332            fp->outPath = HIVIEW_FILE_OUT_PATH_LOG;
333            break;
334        default:
335            break;
336    }
337}
338