1 /*
2 * Copyright (c) 2022-2023 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 } // namespace
48
CopyNulstr(char *dest, size_t size, const char *src)49 size_t Utility::CopyNulstr(char *dest, size_t size, const char *src)
50 {
51 CHKPR(dest, 0);
52 CHKPR(src, 0);
53
54 size_t len = strlen(src);
55 if (len >= size) {
56 if (size > 1) {
57 len = size - 1;
58 } else {
59 len = 0;
60 }
61 }
62 if (len > 0) {
63 errno_t ret = memcpy_s(dest, size, src, len);
64 if (ret != EOK) {
65 FI_HILOGW("memcpy_s:bounds checking failed");
66 }
67 }
68 if (size > 0) {
69 dest[len] = '\0';
70 }
71 return len;
72 }
73
StartWith(const char *str, const char *prefix)74 bool Utility::StartWith(const char *str, const char *prefix)
75 {
76 size_t prefixlen = strlen(prefix);
77 return (prefixlen > 0 ? (strncmp(str, prefix, strlen(prefix)) == 0) : false);
78 }
79
StartWith(const std::string &str, const std::string &prefix)80 bool Utility::StartWith(const std::string &str, const std::string &prefix)
81 {
82 if (str.size() < prefix.size()) {
83 return false;
84 }
85 return (str.compare(0, prefix.size(), prefix) == 0);
86 }
87
RemoveTrailingChars(char c, char *path)88 void Utility::RemoveTrailingChars(char c, char *path)
89 {
90 CHKPV(path);
91 size_t len = strlen(path);
92 while (len > 0 && path[len-1] == c) {
93 path[--len] = '\0';
94 }
95 }
96
RemoveTrailingChars(const std::string &toRemoved, std::string &path)97 void Utility::RemoveTrailingChars(const std::string &toRemoved, std::string &path)
98 {
99 while (!path.empty() && (toRemoved.find(path.back()) != std::string::npos)) {
100 path.pop_back();
101 }
102 }
103
RemoveSpace(std::string &str)104 void Utility::RemoveSpace(std::string &str)
105 {
106 str.erase(remove_if(str.begin(), str.end(), [](unsigned char c) { return std::isspace(c);}), str.end());
107 }
108
IsInteger(const std::string &target)109 bool Utility::IsInteger(const std::string &target)
110 {
111 std::regex pattern("^\\s*-?(0|([1-9]\\d*))\\s*$");
112 return std::regex_match(target, pattern);
113 }
114
Anonymize(const char* id)115 std::string Utility::Anonymize(const char* id)
116 {
117 if (id == nullptr) {
118 return std::string(MULTIPLES * SUBSTR_ID_LENGTH, '*');
119 }
120 std::string idStr(id);
121 if (idStr.empty() || idStr.length() < SUBSTR_ID_LENGTH) {
122 return std::string(MULTIPLES * SUBSTR_ID_LENGTH, '*');
123 }
124 return idStr.substr(0, SUBSTR_ID_LENGTH) + std::string(SUBSTR_ID_LENGTH, '*') +
125 idStr.substr(idStr.length() - SUBSTR_ID_LENGTH);
126 }
127
DoesFileExist(const char *path)128 bool Utility::DoesFileExist(const char *path)
129 {
130 return (access(path, F_OK) == 0);
131 }
132
GetFileSize(const std::string &filePath)133 ssize_t Utility::GetFileSize(const std::string &filePath)
134 {
135 return GetFileSize(filePath.c_str());
136 }
137
GetFileSize(const char *path)138 ssize_t Utility::GetFileSize(const char *path)
139 {
140 struct stat buf {};
141 ssize_t sz { 0 };
142
143 if (stat(path, &buf) == 0) {
144 if (S_ISREG(buf.st_mode)) {
145 sz = buf.st_size;
146 } else {
147 FI_HILOGE("Not regular file:\'%{public}s\'", path);
148 }
149 } else {
150 FI_HILOGE("stat(\'%{public}s\') failed:%{public}s", path, strerror(errno));
151 }
152 return sz;
153 }
154
ShowFileAttributes(const char *path)155 void Utility::ShowFileAttributes(const char *path)
156 {
157 CALL_DEBUG_ENTER;
158 FI_HILOGD("======================= File Attributes ========================");
159 FI_HILOGD("%{public}20s:%{public}s", "FILE NAME", path);
160
161 struct stat buf {};
162 if (stat(path, &buf) != 0) {
163 FI_HILOGE("stat(\'%{public}s\') failed:%{public}s", path, strerror(errno));
164 return;
165 }
166 if (S_ISDIR(buf.st_mode)) {
167 FI_HILOGD("%{public}20s: directory", "TYPE");
168 } else if (S_ISCHR(buf.st_mode)) {
169 FI_HILOGD("%{public}20s: character special file", "TYPE");
170 } else if (S_ISREG(buf.st_mode)) {
171 FI_HILOGD("%{public}20s: regular file", "TYPE");
172 }
173
174 std::ostringstream ss;
175 std::map<mode_t, std::string> modes {{S_IRUSR, "U+R "}, {S_IWUSR, "U+W "}, {S_IXUSR, "U+X "}, {S_IRGRP, "G+R "},
176 {S_IWGRP, "G+W "}, {S_IXGRP, "G+X "}, {S_IROTH, "O+R "}, {S_IWOTH, "O+W "}, {S_IXOTH, "O+X "}};
177 for (const auto &element : modes) {
178 if (buf.st_mode & element.first) {
179 ss << element.second;
180 break;
181 }
182 }
183
184 FI_HILOGD("%{public}20s:%{public}s", "PERMISSIONS", ss.str().c_str());
185 }
186
ShowUserAndGroup()187 void Utility::ShowUserAndGroup()
188 {
189 CALL_DEBUG_ENTER;
190 static constexpr size_t BUFSIZE { 1024 };
191 char buffer[BUFSIZE];
192 struct passwd buf;
193 struct passwd *pbuf = nullptr;
194 struct group grp;
195 struct group *pgrp = nullptr;
196
197 FI_HILOGD("======================= Users and Groups =======================");
198 uid_t uid = getuid();
199 if (getpwuid_r(uid, &buf, buffer, sizeof(buffer), &pbuf) != 0) {
200 FI_HILOGE("getpwuid_r failed:%{public}s", strerror(errno));
201 } else {
202 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "USER", uid, buf.pw_name);
203 }
204
205 gid_t gid = getgid();
206 if (getgrgid_r(gid, &grp, buffer, sizeof(buffer), &pgrp) != 0) {
207 FI_HILOGE("getgrgid_r failed:%{public}s", strerror(errno));
208 } else {
209 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "GROUP", gid, grp.gr_name);
210 }
211
212 uid = geteuid();
213 if (getpwuid_r(uid, &buf, buffer, sizeof(buffer), &pbuf) != 0) {
214 FI_HILOGE("getpwuid_r failed:%{public}s", strerror(errno));
215 } else {
216 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "EFFECTIVE USER", uid, buf.pw_name);
217 }
218
219 gid = getegid();
220 if (getgrgid_r(gid, &grp, buffer, sizeof(buffer), &pgrp) != 0) {
221 FI_HILOGE("getgrgid_r failed:%{public}s", strerror(errno));
222 } else {
223 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "EFFECTIVE GROUP", gid, grp.gr_name);
224 }
225
226 gid_t groups[NGROUPS_MAX + 1];
227 int32_t ngrps = getgroups(sizeof(groups), groups);
228 for (int32_t i = 0; i < ngrps; ++i) {
229 if (getgrgid_r(groups[i], &grp, buffer, sizeof(buffer), &pgrp) != 0) {
230 FI_HILOGE("getgrgid_r failed:%{public}s", strerror(errno));
231 } else {
232 FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "SUPPLEMENTARY GROUP", groups[i], grp.gr_name);
233 }
234 }
235 }
236
GetSysClockTime()237 int64_t Utility::GetSysClockTime()
238 {
239 return std::chrono::time_point_cast<std::chrono::microseconds>(
240 std::chrono::steady_clock::now()).time_since_epoch().count();
241 }
242 } // namespace DeviceStatus
243 } // namespace Msdp
244 } // namespace OHOS
245