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