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