1 /*
2 * Copyright (c) 2022-2025 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 "utility.h"
17
18 #include <grp.h>
19 #include <pwd.h>
20 #include <unistd.h>
21
22 #include <cerrno>
23 #include <chrono>
24 #include <limits>
25 #include <map>
26 #include <regex>
27 #include <sstream>
28
29 #include <sys/stat.h>
30 #include <sys/types.h>
31
32 #include "parcel.h"
33 #include "securec.h"
34
35 #include "devicestatus_common.h"
36 #include "devicestatus_define.h"
37
38 #undef LOG_TAG
39 #define LOG_TAG "Utility"
40
41 namespace OHOS {
42 namespace Msdp {
43 namespace DeviceStatus {
44 namespace {
45 constexpr size_t SUBSTR_ID_LENGTH { 5 };
46 constexpr int32_t MULTIPLES { 2 };
47 constexpr size_t DFX_RADAR_MASK_SIZE { 2 };
48 constexpr int64_t TIME_CONVERSION_UNIT { 1000 };
49 constexpr int64_t TIME_ROUND_UP { 999 };
50 } // namespace
51
CopyNulstr(char * dest,size_t size,const char * src)52 size_t Utility::CopyNulstr(char *dest, size_t size, const char *src)
53 {
54 CHKPR(dest, 0);
55 CHKPR(src, 0);
56
57 size_t len = strlen(src);
58 if (len >= size) {
59 if (size > 1) {
60 len = size - 1;
61 } else {
62 len = 0;
63 }
64 }
65 if (len > 0) {
66 errno_t ret = memcpy_s(dest, size, src, len);
67 if (ret != EOK) {
68 FI_HILOGW("memcpy_s:bounds checking failed");
69 }
70 }
71 if (size > 0) {
72 dest[len] = '\0';
73 }
74 return len;
75 }
76
StartWith(const char * str,const char * prefix)77 bool Utility::StartWith(const char *str, const char *prefix)
78 {
79 size_t prefixlen = strlen(prefix);
80 return (prefixlen > 0 ? (strncmp(str, prefix, strlen(prefix)) == 0) : false);
81 }
82
StartWith(const std::string & str,const std::string & prefix)83 bool Utility::StartWith(const std::string &str, const std::string &prefix)
84 {
85 if (str.size() < prefix.size()) {
86 return false;
87 }
88 return (str.compare(0, prefix.size(), prefix) == 0);
89 }
90
RemoveTrailingChars(char c,char * path)91 void Utility::RemoveTrailingChars(char c, char *path)
92 {
93 CHKPV(path);
94 size_t len = strlen(path);
95 while (len > 0 && path[len-1] == c) {
96 path[--len] = '\0';
97 }
98 }
99
RemoveTrailingChars(const std::string & toRemoved,std::string & path)100 void Utility::RemoveTrailingChars(const std::string &toRemoved, std::string &path)
101 {
102 while (!path.empty() && (toRemoved.find(path.back()) != std::string::npos)) {
103 path.pop_back();
104 }
105 }
106
RemoveSpace(std::string & str)107 void Utility::RemoveSpace(std::string &str)
108 {
109 str.erase(remove_if(str.begin(), str.end(), [](unsigned char c) { return std::isspace(c);}), str.end());
110 }
111
IsInteger(const std::string & target)112 bool Utility::IsInteger(const std::string &target)
113 {
114 std::regex pattern("^\\s*-?(0|([1-9]\\d*))\\s*$");
115 return std::regex_match(target, pattern);
116 }
117
Anonymize(const char * id)118 std::string Utility::Anonymize(const char* id)
119 {
120 if (id == nullptr) {
121 return std::string(MULTIPLES * SUBSTR_ID_LENGTH, '*');
122 }
123 std::string idStr(id);
124 if (idStr.empty() || idStr.length() < SUBSTR_ID_LENGTH) {
125 return std::string(MULTIPLES * SUBSTR_ID_LENGTH, '*');
126 }
127 return idStr.substr(0, SUBSTR_ID_LENGTH) + std::string(SUBSTR_ID_LENGTH, '*') +
128 idStr.substr(idStr.length() - SUBSTR_ID_LENGTH);
129 }
130
DFXRadarAnonymize(const char * id)131 std::string Utility::DFXRadarAnonymize(const char* id)
132 {
133 if (id == nullptr) {
134 return std::string(MULTIPLES * SUBSTR_ID_LENGTH, '*');
135 }
136 std::string idStr(id);
137 if (idStr.empty() || idStr.length() < SUBSTR_ID_LENGTH) {
138 return std::string(MULTIPLES * SUBSTR_ID_LENGTH, '*');
139 }
140 return idStr.substr(0, SUBSTR_ID_LENGTH) + std::string(DFX_RADAR_MASK_SIZE, '*') +
141 idStr.substr(idStr.length() - SUBSTR_ID_LENGTH);
142 }
143
DoesFileExist(const char * path)144 bool Utility::DoesFileExist(const char *path)
145 {
146 return (access(path, F_OK) == 0);
147 }
148
GetFileSize(const std::string & filePath)149 ssize_t Utility::GetFileSize(const std::string &filePath)
150 {
151 return GetFileSize(filePath.c_str());
152 }
153
GetFileSize(const char * path)154 ssize_t Utility::GetFileSize(const char *path)
155 {
156 struct stat buf {};
157 ssize_t sz { 0 };
158
159 if (stat(path, &buf) == 0) {
160 if (S_ISREG(buf.st_mode)) {
161 sz = buf.st_size;
162 } else {
163 FI_HILOGE("Not regular file:\'%{private}s\'", path);
164 }
165 } else {
166 FI_HILOGE("stat(\'%{private}s\') failed:%{public}s", path, strerror(errno));
167 }
168 return sz;
169 }
170
ShowFileAttributes(const char * path)171 void Utility::ShowFileAttributes(const char *path)
172 {
173 CALL_DEBUG_ENTER;
174 FI_HILOGD("======================= File Attributes ========================");
175 FI_HILOGD("%{public}20s:%{private}s", "FILE NAME", path);
176
177 struct stat buf {};
178 if (stat(path, &buf) != 0) {
179 FI_HILOGE("stat(\'%{private}s\') failed:%{public}s", path, strerror(errno));
180 return;
181 }
182 if (S_ISDIR(buf.st_mode)) {
183 FI_HILOGD("%{public}20s: directory", "TYPE");
184 } else if (S_ISCHR(buf.st_mode)) {
185 FI_HILOGD("%{public}20s: character special file", "TYPE");
186 } else if (S_ISREG(buf.st_mode)) {
187 FI_HILOGD("%{public}20s: regular file", "TYPE");
188 }
189
190 std::ostringstream ss;
191 std::map<mode_t, std::string> modes {{S_IRUSR, "U+R "}, {S_IWUSR, "U+W "}, {S_IXUSR, "U+X "}, {S_IRGRP, "G+R "},
192 {S_IWGRP, "G+W "}, {S_IXGRP, "G+X "}, {S_IROTH, "O+R "}, {S_IWOTH, "O+W "}, {S_IXOTH, "O+X "}};
193 for (const auto &element : modes) {
194 if (buf.st_mode & element.first) {
195 ss << element.second;
196 break;
197 }
198 }
199
200 FI_HILOGD("%{public}20s:%{public}s", "PERMISSIONS", ss.str().c_str());
201 }
202
ShowUserAndGroup()203 void Utility::ShowUserAndGroup()
204 {
205 CALL_DEBUG_ENTER;
206 static constexpr size_t BUFSIZE { 1024 };
207 char buffer[BUFSIZE];
208 struct passwd buf;
209 struct passwd *pbuf = nullptr;
210 struct group grp;
211 struct group *pgrp = nullptr;
212
213 FI_HILOGD("======================= Users and Groups =======================");
214 uid_t uid = getuid();
215 if (getpwuid_r(uid, &buf, buffer, sizeof(buffer), &pbuf) != 0) {
216 FI_HILOGE("getpwuid_r failed:%{public}s", strerror(errno));
217 } else {
218 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "USER", uid, buf.pw_name);
219 }
220
221 gid_t gid = getgid();
222 if (getgrgid_r(gid, &grp, buffer, sizeof(buffer), &pgrp) != 0) {
223 FI_HILOGE("getgrgid_r failed:%{public}s", strerror(errno));
224 } else {
225 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "GROUP", gid, grp.gr_name);
226 }
227
228 uid = geteuid();
229 if (getpwuid_r(uid, &buf, buffer, sizeof(buffer), &pbuf) != 0) {
230 FI_HILOGE("getpwuid_r failed:%{public}s", strerror(errno));
231 } else {
232 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "EFFECTIVE USER", uid, buf.pw_name);
233 }
234
235 gid = getegid();
236 if (getgrgid_r(gid, &grp, buffer, sizeof(buffer), &pgrp) != 0) {
237 FI_HILOGE("getgrgid_r failed:%{public}s", strerror(errno));
238 } else {
239 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "EFFECTIVE GROUP", gid, grp.gr_name);
240 }
241
242 gid_t groups[NGROUPS_MAX + 1];
243 int32_t ngrps = getgroups(sizeof(groups), groups);
244 for (int32_t i = 0; i < ngrps; ++i) {
245 if (getgrgid_r(groups[i], &grp, buffer, sizeof(buffer), &pgrp) != 0) {
246 FI_HILOGE("getgrgid_r failed:%{public}s", strerror(errno));
247 } else {
248 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "SUPPLEMENTARY GROUP", groups[i], grp.gr_name);
249 }
250 }
251 }
252
GetSysClockTime()253 int64_t Utility::GetSysClockTime()
254 {
255 struct timespec ts = { 0, 0 };
256 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
257 FI_HILOGD("clock_gettime failed:%{public}d", errno);
258 return 0;
259 }
260
261 if (static_cast<uint64_t>(ts.tv_sec) > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) / (
262 TIME_CONVERSION_UNIT * TIME_CONVERSION_UNIT)) {
263 FI_HILOGE("Integer overflow detected!");
264 return 0;
265 }
266
267 uint64_t totalMicroSeconds = static_cast<uint64_t>(ts.tv_sec) * TIME_CONVERSION_UNIT *
268 TIME_CONVERSION_UNIT + static_cast<uint64_t>(ts.tv_nsec) / TIME_CONVERSION_UNIT;
269
270 if (totalMicroSeconds > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
271 FI_HILOGE("Total time value integer overflow detected!");
272 return 0;
273 }
274 return static_cast<int64_t>(totalMicroSeconds);
275 }
276
GetSysClockTimeMilli(int64_t timeDT)277 int64_t Utility::GetSysClockTimeMilli(int64_t timeDT)
278 {
279 return (timeDT + TIME_ROUND_UP) / TIME_CONVERSION_UNIT;
280 }
281 } // namespace DeviceStatus
282 } // namespace Msdp
283 } // namespace OHOS
284