1 /*
2 * Copyright (c) 2023-2024 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 "common_util.h"
17
18 #include <regex>
19
20 #include "file_util.h"
21 #include "hiview_logger.h"
22 #include "string_util.h"
23 #include "time_util.h"
24
25 namespace OHOS {
26 namespace HiviewDFX {
27 namespace UCollectUtil {
28 namespace {
29 DEFINE_LOG_TAG("UCollectUtil-CommonUtil");
30 const std::string EXPORT_FILE_REGEX = "[0-9]{14}(.*)";
31 const std::string UNDERLINE = "_";
32 }
33
StrToNum(const std::string & sString,T & tX)34 template <typename T> bool CommonUtil::StrToNum(const std::string &sString, T &tX)
35 {
36 std::istringstream iStream(sString);
37 return (iStream >> tX) ? true : false;
38 }
39
ParseTypeAndValue(const std::string & str,std::string & type,int32_t & value)40 bool CommonUtil::ParseTypeAndValue(const std::string &str, std::string &type, int32_t &value)
41 {
42 std::string::size_type typePos = str.find(":");
43 if (typePos != std::string::npos) {
44 type = str.substr(0, typePos);
45 std::string valueStr = str.substr(typePos + 1);
46 std::string::size_type valuePos = valueStr.find("kB");
47 if (valuePos == std::string::npos) {
48 valuePos = valueStr.find("KB");
49 }
50 if (valuePos != std::string::npos) {
51 valueStr.resize(valuePos);
52 StrToNum(valueStr, value);
53 return true;
54 } else {
55 StrToNum(valueStr, value);
56 return true;
57 }
58 }
59 return false;
60 }
61
GetDirRegexFiles(const std::string & path,const std::string & pattern,std::vector<std::string> & files)62 void CommonUtil::GetDirRegexFiles(const std::string& path, const std::string& pattern,
63 std::vector<std::string>& files)
64 {
65 DIR* dir = opendir(path.c_str());
66 if (dir == nullptr) {
67 HIVIEW_LOGE("failed to open dir=%{public}s", path.c_str());
68 return;
69 }
70 std::regex reg = std::regex(pattern);
71 struct dirent* ptr = nullptr;
72 while ((ptr = readdir(dir)) != nullptr) {
73 if (ptr->d_type == DT_REG) {
74 if (regex_match(ptr->d_name, reg)) {
75 files.push_back(FileUtil::IncludeTrailingPathDelimiter(path) + std::string(ptr->d_name));
76 }
77 }
78 }
79 closedir(dir);
80 std::sort(files.begin(), files.end());
81 }
82
GetFileNameNum(const std::string & fileName,const std::string & ext)83 int CommonUtil::GetFileNameNum(const std::string& fileName, const std::string& ext)
84 {
85 int ret = 0;
86 auto startPos = fileName.find(UNDERLINE);
87 if (startPos == std::string::npos) {
88 return ret;
89 }
90 auto endPos = fileName.find(ext);
91 if (endPos == std::string::npos) {
92 return ret;
93 }
94 if (endPos <= startPos + 1) {
95 return ret;
96 }
97 return StringUtil::StrToInt(fileName.substr(startPos + 1, endPos - startPos - 1));
98 }
99
CreateExportFile(const std::string & path,int32_t maxFileNum,const std::string & prefix,const std::string & ext)100 std::string CommonUtil::CreateExportFile(const std::string& path, int32_t maxFileNum, const std::string& prefix,
101 const std::string& ext)
102 {
103 if (!FileUtil::IsDirectory(path) && !FileUtil::ForceCreateDirectory(path)) {
104 HIVIEW_LOGE("failed to create dir=%{public}s", path.c_str());
105 return "";
106 }
107
108 std::vector<std::string> files;
109 GetDirRegexFiles(path, prefix + EXPORT_FILE_REGEX, files);
110 if (files.size() >= static_cast<size_t>(maxFileNum)) {
111 for (size_t index = 0; index <= files.size() - static_cast<size_t>(maxFileNum); ++index) {
112 HIVIEW_LOGI("remove file=%{public}s", FileUtil::ExtractFileName(files[index]).c_str());
113 (void)FileUtil::RemoveFile(files[index]);
114 }
115 }
116
117 uint64_t fileTime = TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC;
118 std::string timeFormat = TimeUtil::TimestampFormatToDate(fileTime, "%Y%m%d%H%M%S");
119 std::string fileName;
120 fileName.append(path).append(prefix).append(timeFormat);
121 if (!files.empty()) {
122 auto startPos = files.back().find(timeFormat);
123 if (startPos != std::string::npos) {
124 int fileNameNum = GetFileNameNum(files.back().substr(startPos), ext); // yyyymmddHHMMSS_1.txt
125 fileName.append(UNDERLINE).append(std::to_string(++fileNameNum));
126 }
127 }
128 fileName.append(ext);
129 (void)FileUtil::CreateFile(fileName);
130 HIVIEW_LOGI("create file=%{public}s", FileUtil::ExtractFileName(fileName).c_str());
131 return fileName;
132 }
133
ReadNodeWithOnlyNumber(const std::string & fileName)134 int32_t CommonUtil::ReadNodeWithOnlyNumber(const std::string& fileName)
135 {
136 std::string content;
137 if (!FileUtil::LoadStringFromFile(fileName, content)) {
138 HIVIEW_LOGW("read node failed");
139 return 0;
140 }
141 int32_t parsedVal = 0;
142 // this string content might be empty or consist of some special charactors
143 // so "std::stoi" and "StringUtil::StrToInt" aren't applicable here.
144 std::stringstream ss(content);
145 ss >> parsedVal;
146 return parsedVal;
147 }
148 } // UCollectUtil
149 } // HiViewDFX
150 } // OHOS
151