1f857971dSopenharmony_ci/*
2f857971dSopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3f857971dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4f857971dSopenharmony_ci * you may not use this file except in compliance with the License.
5f857971dSopenharmony_ci * You may obtain a copy of the License at
6f857971dSopenharmony_ci *
7f857971dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8f857971dSopenharmony_ci *
9f857971dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10f857971dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11f857971dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f857971dSopenharmony_ci * See the License for the specific language governing permissions and
13f857971dSopenharmony_ci * limitations under the License.
14f857971dSopenharmony_ci */
15f857971dSopenharmony_ci
16f857971dSopenharmony_ci#include "utility.h"
17f857971dSopenharmony_ci
18f857971dSopenharmony_ci#include <grp.h>
19f857971dSopenharmony_ci#include <pwd.h>
20f857971dSopenharmony_ci#include <unistd.h>
21f857971dSopenharmony_ci
22f857971dSopenharmony_ci#include <cerrno>
23f857971dSopenharmony_ci#include <chrono>
24f857971dSopenharmony_ci#include <limits>
25f857971dSopenharmony_ci#include <map>
26f857971dSopenharmony_ci#include <regex>
27f857971dSopenharmony_ci#include <sstream>
28f857971dSopenharmony_ci
29f857971dSopenharmony_ci#include <sys/stat.h>
30f857971dSopenharmony_ci#include <sys/types.h>
31f857971dSopenharmony_ci
32f857971dSopenharmony_ci#include "parcel.h"
33f857971dSopenharmony_ci#include "securec.h"
34f857971dSopenharmony_ci
35f857971dSopenharmony_ci#include "devicestatus_common.h"
36f857971dSopenharmony_ci#include "devicestatus_define.h"
37f857971dSopenharmony_ci
38f857971dSopenharmony_ci#undef LOG_TAG
39f857971dSopenharmony_ci#define LOG_TAG "Utility"
40f857971dSopenharmony_ci
41f857971dSopenharmony_cinamespace OHOS {
42f857971dSopenharmony_cinamespace Msdp {
43f857971dSopenharmony_cinamespace DeviceStatus {
44f857971dSopenharmony_cinamespace {
45f857971dSopenharmony_ciconstexpr size_t SUBSTR_ID_LENGTH { 5 };
46f857971dSopenharmony_ciconstexpr int32_t MULTIPLES { 2 };
47f857971dSopenharmony_ci} // namespace
48f857971dSopenharmony_ci
49f857971dSopenharmony_cisize_t Utility::CopyNulstr(char *dest, size_t size, const char *src)
50f857971dSopenharmony_ci{
51f857971dSopenharmony_ci    CHKPR(dest, 0);
52f857971dSopenharmony_ci    CHKPR(src, 0);
53f857971dSopenharmony_ci
54f857971dSopenharmony_ci    size_t len = strlen(src);
55f857971dSopenharmony_ci    if (len >= size) {
56f857971dSopenharmony_ci        if (size > 1) {
57f857971dSopenharmony_ci            len = size - 1;
58f857971dSopenharmony_ci        } else {
59f857971dSopenharmony_ci            len = 0;
60f857971dSopenharmony_ci        }
61f857971dSopenharmony_ci    }
62f857971dSopenharmony_ci    if (len > 0) {
63f857971dSopenharmony_ci        errno_t ret = memcpy_s(dest, size, src, len);
64f857971dSopenharmony_ci        if (ret != EOK) {
65f857971dSopenharmony_ci            FI_HILOGW("memcpy_s:bounds checking failed");
66f857971dSopenharmony_ci        }
67f857971dSopenharmony_ci    }
68f857971dSopenharmony_ci    if (size > 0) {
69f857971dSopenharmony_ci        dest[len] = '\0';
70f857971dSopenharmony_ci    }
71f857971dSopenharmony_ci    return len;
72f857971dSopenharmony_ci}
73f857971dSopenharmony_ci
74f857971dSopenharmony_cibool Utility::StartWith(const char *str, const char *prefix)
75f857971dSopenharmony_ci{
76f857971dSopenharmony_ci    size_t prefixlen = strlen(prefix);
77f857971dSopenharmony_ci    return (prefixlen > 0 ? (strncmp(str, prefix, strlen(prefix)) == 0) : false);
78f857971dSopenharmony_ci}
79f857971dSopenharmony_ci
80f857971dSopenharmony_cibool Utility::StartWith(const std::string &str, const std::string &prefix)
81f857971dSopenharmony_ci{
82f857971dSopenharmony_ci    if (str.size() < prefix.size()) {
83f857971dSopenharmony_ci        return false;
84f857971dSopenharmony_ci    }
85f857971dSopenharmony_ci    return (str.compare(0, prefix.size(), prefix) == 0);
86f857971dSopenharmony_ci}
87f857971dSopenharmony_ci
88f857971dSopenharmony_civoid Utility::RemoveTrailingChars(char c, char *path)
89f857971dSopenharmony_ci{
90f857971dSopenharmony_ci    CHKPV(path);
91f857971dSopenharmony_ci    size_t len = strlen(path);
92f857971dSopenharmony_ci    while (len > 0 && path[len-1] == c) {
93f857971dSopenharmony_ci        path[--len] = '\0';
94f857971dSopenharmony_ci    }
95f857971dSopenharmony_ci}
96f857971dSopenharmony_ci
97f857971dSopenharmony_civoid Utility::RemoveTrailingChars(const std::string &toRemoved, std::string &path)
98f857971dSopenharmony_ci{
99f857971dSopenharmony_ci    while (!path.empty() && (toRemoved.find(path.back()) != std::string::npos)) {
100f857971dSopenharmony_ci        path.pop_back();
101f857971dSopenharmony_ci    }
102f857971dSopenharmony_ci}
103f857971dSopenharmony_ci
104f857971dSopenharmony_civoid Utility::RemoveSpace(std::string &str)
105f857971dSopenharmony_ci{
106f857971dSopenharmony_ci    str.erase(remove_if(str.begin(), str.end(), [](unsigned char c) { return std::isspace(c);}), str.end());
107f857971dSopenharmony_ci}
108f857971dSopenharmony_ci
109f857971dSopenharmony_cibool Utility::IsInteger(const std::string &target)
110f857971dSopenharmony_ci{
111f857971dSopenharmony_ci    std::regex pattern("^\\s*-?(0|([1-9]\\d*))\\s*$");
112f857971dSopenharmony_ci    return std::regex_match(target, pattern);
113f857971dSopenharmony_ci}
114f857971dSopenharmony_ci
115f857971dSopenharmony_cistd::string Utility::Anonymize(const char* id)
116f857971dSopenharmony_ci{
117f857971dSopenharmony_ci    if (id == nullptr) {
118f857971dSopenharmony_ci        return std::string(MULTIPLES * SUBSTR_ID_LENGTH, '*');
119f857971dSopenharmony_ci    }
120f857971dSopenharmony_ci    std::string idStr(id);
121f857971dSopenharmony_ci    if (idStr.empty() || idStr.length() < SUBSTR_ID_LENGTH) {
122f857971dSopenharmony_ci        return std::string(MULTIPLES * SUBSTR_ID_LENGTH, '*');
123f857971dSopenharmony_ci    }
124f857971dSopenharmony_ci    return idStr.substr(0, SUBSTR_ID_LENGTH) + std::string(SUBSTR_ID_LENGTH, '*') +
125f857971dSopenharmony_ci        idStr.substr(idStr.length() - SUBSTR_ID_LENGTH);
126f857971dSopenharmony_ci}
127f857971dSopenharmony_ci
128f857971dSopenharmony_cibool Utility::DoesFileExist(const char *path)
129f857971dSopenharmony_ci{
130f857971dSopenharmony_ci    return (access(path, F_OK) == 0);
131f857971dSopenharmony_ci}
132f857971dSopenharmony_ci
133f857971dSopenharmony_cissize_t Utility::GetFileSize(const std::string &filePath)
134f857971dSopenharmony_ci{
135f857971dSopenharmony_ci    return GetFileSize(filePath.c_str());
136f857971dSopenharmony_ci}
137f857971dSopenharmony_ci
138f857971dSopenharmony_cissize_t Utility::GetFileSize(const char *path)
139f857971dSopenharmony_ci{
140f857971dSopenharmony_ci    struct stat buf {};
141f857971dSopenharmony_ci    ssize_t sz { 0 };
142f857971dSopenharmony_ci
143f857971dSopenharmony_ci    if (stat(path, &buf) == 0) {
144f857971dSopenharmony_ci        if (S_ISREG(buf.st_mode)) {
145f857971dSopenharmony_ci            sz = buf.st_size;
146f857971dSopenharmony_ci        } else {
147f857971dSopenharmony_ci            FI_HILOGE("Not regular file:\'%{public}s\'", path);
148f857971dSopenharmony_ci        }
149f857971dSopenharmony_ci    } else {
150f857971dSopenharmony_ci        FI_HILOGE("stat(\'%{public}s\') failed:%{public}s", path, strerror(errno));
151f857971dSopenharmony_ci    }
152f857971dSopenharmony_ci    return sz;
153f857971dSopenharmony_ci}
154f857971dSopenharmony_ci
155f857971dSopenharmony_civoid Utility::ShowFileAttributes(const char *path)
156f857971dSopenharmony_ci{
157f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
158f857971dSopenharmony_ci    FI_HILOGD("======================= File Attributes ========================");
159f857971dSopenharmony_ci    FI_HILOGD("%{public}20s:%{public}s", "FILE NAME", path);
160f857971dSopenharmony_ci
161f857971dSopenharmony_ci    struct stat buf {};
162f857971dSopenharmony_ci    if (stat(path, &buf) != 0) {
163f857971dSopenharmony_ci        FI_HILOGE("stat(\'%{public}s\') failed:%{public}s", path, strerror(errno));
164f857971dSopenharmony_ci        return;
165f857971dSopenharmony_ci    }
166f857971dSopenharmony_ci    if (S_ISDIR(buf.st_mode)) {
167f857971dSopenharmony_ci        FI_HILOGD("%{public}20s: directory", "TYPE");
168f857971dSopenharmony_ci    } else if (S_ISCHR(buf.st_mode)) {
169f857971dSopenharmony_ci        FI_HILOGD("%{public}20s: character special file", "TYPE");
170f857971dSopenharmony_ci    } else if (S_ISREG(buf.st_mode)) {
171f857971dSopenharmony_ci        FI_HILOGD("%{public}20s: regular file", "TYPE");
172f857971dSopenharmony_ci    }
173f857971dSopenharmony_ci
174f857971dSopenharmony_ci    std::ostringstream ss;
175f857971dSopenharmony_ci    std::map<mode_t, std::string> modes {{S_IRUSR, "U+R "}, {S_IWUSR, "U+W "}, {S_IXUSR, "U+X "}, {S_IRGRP, "G+R "},
176f857971dSopenharmony_ci        {S_IWGRP, "G+W "}, {S_IXGRP, "G+X "}, {S_IROTH, "O+R "}, {S_IWOTH, "O+W "}, {S_IXOTH, "O+X "}};
177f857971dSopenharmony_ci    for (const auto &element : modes) {
178f857971dSopenharmony_ci        if (buf.st_mode & element.first) {
179f857971dSopenharmony_ci            ss << element.second;
180f857971dSopenharmony_ci            break;
181f857971dSopenharmony_ci        }
182f857971dSopenharmony_ci    }
183f857971dSopenharmony_ci
184f857971dSopenharmony_ci    FI_HILOGD("%{public}20s:%{public}s", "PERMISSIONS", ss.str().c_str());
185f857971dSopenharmony_ci}
186f857971dSopenharmony_ci
187f857971dSopenharmony_civoid Utility::ShowUserAndGroup()
188f857971dSopenharmony_ci{
189f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
190f857971dSopenharmony_ci    static constexpr size_t BUFSIZE { 1024 };
191f857971dSopenharmony_ci    char buffer[BUFSIZE];
192f857971dSopenharmony_ci    struct passwd buf;
193f857971dSopenharmony_ci    struct passwd *pbuf = nullptr;
194f857971dSopenharmony_ci    struct group grp;
195f857971dSopenharmony_ci    struct group *pgrp = nullptr;
196f857971dSopenharmony_ci
197f857971dSopenharmony_ci    FI_HILOGD("======================= Users and Groups =======================");
198f857971dSopenharmony_ci    uid_t uid = getuid();
199f857971dSopenharmony_ci    if (getpwuid_r(uid, &buf, buffer, sizeof(buffer), &pbuf) != 0) {
200f857971dSopenharmony_ci        FI_HILOGE("getpwuid_r failed:%{public}s", strerror(errno));
201f857971dSopenharmony_ci    } else {
202f857971dSopenharmony_ci        FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "USER", uid, buf.pw_name);
203f857971dSopenharmony_ci    }
204f857971dSopenharmony_ci
205f857971dSopenharmony_ci    gid_t gid = getgid();
206f857971dSopenharmony_ci    if (getgrgid_r(gid, &grp, buffer, sizeof(buffer), &pgrp) != 0) {
207f857971dSopenharmony_ci        FI_HILOGE("getgrgid_r failed:%{public}s", strerror(errno));
208f857971dSopenharmony_ci    } else {
209f857971dSopenharmony_ci        FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "GROUP", gid, grp.gr_name);
210f857971dSopenharmony_ci    }
211f857971dSopenharmony_ci
212f857971dSopenharmony_ci    uid = geteuid();
213f857971dSopenharmony_ci    if (getpwuid_r(uid, &buf, buffer, sizeof(buffer), &pbuf) != 0) {
214f857971dSopenharmony_ci        FI_HILOGE("getpwuid_r failed:%{public}s", strerror(errno));
215f857971dSopenharmony_ci    } else {
216f857971dSopenharmony_ci        FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "EFFECTIVE USER", uid, buf.pw_name);
217f857971dSopenharmony_ci    }
218f857971dSopenharmony_ci
219f857971dSopenharmony_ci    gid = getegid();
220f857971dSopenharmony_ci    if (getgrgid_r(gid, &grp, buffer, sizeof(buffer), &pgrp) != 0) {
221f857971dSopenharmony_ci        FI_HILOGE("getgrgid_r failed:%{public}s", strerror(errno));
222f857971dSopenharmony_ci    } else {
223f857971dSopenharmony_ci        FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "EFFECTIVE GROUP", gid, grp.gr_name);
224f857971dSopenharmony_ci    }
225f857971dSopenharmony_ci
226f857971dSopenharmony_ci    gid_t groups[NGROUPS_MAX + 1];
227f857971dSopenharmony_ci    int32_t ngrps = getgroups(sizeof(groups), groups);
228f857971dSopenharmony_ci    for (int32_t i = 0; i < ngrps; ++i) {
229f857971dSopenharmony_ci        if (getgrgid_r(groups[i], &grp, buffer, sizeof(buffer), &pgrp) != 0) {
230f857971dSopenharmony_ci            FI_HILOGE("getgrgid_r failed:%{public}s", strerror(errno));
231f857971dSopenharmony_ci        } else {
232f857971dSopenharmony_ci            FI_HILOGD("%{public}20s:%{public}10u%{public}20s", "SUPPLEMENTARY GROUP", groups[i], grp.gr_name);
233f857971dSopenharmony_ci        }
234f857971dSopenharmony_ci    }
235f857971dSopenharmony_ci}
236f857971dSopenharmony_ci
237f857971dSopenharmony_ciint64_t Utility::GetSysClockTime()
238f857971dSopenharmony_ci{
239f857971dSopenharmony_ci    return std::chrono::time_point_cast<std::chrono::microseconds>(
240f857971dSopenharmony_ci            std::chrono::steady_clock::now()).time_since_epoch().count();
241f857971dSopenharmony_ci}
242f857971dSopenharmony_ci} // namespace DeviceStatus
243f857971dSopenharmony_ci} // namespace Msdp
244f857971dSopenharmony_ci} // namespace OHOS
245