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