1/*
2 * Copyright (c) 2021 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#include "log_util.h"
16
17#include <cstring>
18#include <fcntl.h>
19#include <fstream>
20#include <sstream>
21#include <unistd.h>
22
23#include "file_util.h"
24#include "hiview_logger.h"
25#include "string_util.h"
26
27using namespace std;
28namespace OHOS {
29namespace HiviewDFX {
30DEFINE_LOG_TAG("LogUtil");
31
32namespace {
33    const string ARROW = "->";
34    const string CODE = "code";
35    const string WAIT = "wait";
36    const int BUF_LEN_2048 = 2048;
37    const int TOTAL_SKIP_NUM = 4;
38}
39
40const std::string LogUtil::SPLIT_PATTERN = "\n";
41const std::string LogUtil::SMART_PARSER_TEST_DIR = "/data/test/test_data/SmartParser";
42const int LogUtil::TOTAL_LINE_NUM = 200;
43
44/* GetTrace function:
45 * buffer : log buffer
46 * cursor : buffer seekg
47 * reg : regex which is used to get trace line
48 * result : all trace line will be spliced by "\n"
49 * startReg : start place when regex is match, default empty string
50 */
51void LogUtil::GetTrace(stringstream& buffer, int cursor, const string& reg, string& result, string startReg)
52{
53    buffer.seekg(cursor, ios::beg);
54    string line;
55    bool start = false;
56    int num = 0;
57    int skipNum = 0;
58    startReg = startReg.empty() ? reg : startReg;
59
60    while (getline(buffer, line) && num++ < TOTAL_LINE_NUM) {
61        if (line.length() > BUF_LEN_2048) {
62            continue;
63        }
64        if (line.size() == 0 || skipNum >= TOTAL_SKIP_NUM) {
65            break; // blank line
66        }
67        if (!start) {
68            start = regex_search(line, regex(startReg));
69            if (!start) {
70                continue;
71            }
72        }
73
74        smatch matches;
75        if (regex_search(line, matches, regex(reg))) {
76            skipNum = 0;
77        } else {
78            skipNum++;
79            continue;
80        }
81        result += matches.str(0) + LogUtil::SPLIT_PATTERN;
82    }
83}
84
85bool LogUtil::ReadFileBuff(const string& file, stringstream& buffer)
86{
87    int fd = LogUtil::GetFileFd(file);
88    if (fd < 0) {
89        HIVIEW_LOGE("%{public}s get fd fail, fd is %{public}d.", file.c_str(), fd);
90        return false;
91    }
92
93    std::string content;
94    if (!FileUtil::LoadStringFromFd(fd, content)) {
95        HIVIEW_LOGE("read file: %s failed, fd is %d\n", file.c_str(), fd);
96        close(fd);
97        return false;
98    }
99    buffer.str(content);
100    close(fd);
101    return true;
102}
103
104int LogUtil::GetFileFd(const string& file)
105{
106    if (file.empty() || !FileUtil::IsLegalPath(file)) {
107        HIVIEW_LOGE("the system file (%{public}s) is illegal.", file.c_str());
108        return -1;
109    }
110    std::string realFileName;
111    if (!FileUtil::PathToRealPath(file, realFileName) || realFileName.empty() ||
112        !FileUtil::FileExists(realFileName)) {
113        HIVIEW_LOGE("the system file (%{public}s) is not found.", realFileName.c_str());
114        return -1;
115    }
116    return open(realFileName.c_str(), O_RDONLY);
117}
118
119bool LogUtil::FileExist(const string& file)
120{
121    return FileUtil::FileExists(file);
122}
123
124bool LogUtil::IsTestModel(const string& sourceFile, const string& name,
125    const string& pattern, string& desPath)
126{
127    if (FileUtil::IsDirectory(LogUtil::SMART_PARSER_TEST_DIR)) {
128        HIVIEW_LOGI("test dir exist.");
129        std::string sourceFileName = StringUtil::GetRrightSubstr(sourceFile, "/");
130        std::string dirOrFileName = StringUtil::GetRrightSubstr(name, "/");
131        std::string fileName = pattern.find("/") != std::string::npos ?
132            StringUtil::GetRrightSubstr(pattern, "/") : pattern;
133        smatch result;
134        if (regex_match(sourceFileName, result, regex(dirOrFileName)) ||
135            regex_match(sourceFileName, result, regex(fileName))) {
136            return LogUtil::FileExist(desPath);
137        }
138        return false;
139    }
140    return false;
141}
142} // namespace HiviewDFX
143} // namespace OHOS