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 "include/util.h"
17
18 #include <regex>
19 #include <string>
20
21 #ifndef OHOS_BUILD_ENABLE_ARKUI_X
22 #include <sys/prctl.h>
23 #endif // OHOS_BUILD_ENABLE_ARKUI_X
24 #include <sys/stat.h>
25 #include <sys/syscall.h>
26 #include <unistd.h>
27
28 #ifndef OHOS_BUILD_ENABLE_ARKUI_X
29 #include "parameters.h"
30 #endif // OHOS_BUILD_ENABLE_ARKUI_X
31 #include "securec.h"
32
33 #include "devicestatus_define.h"
34 #include "utility.h"
35
36 #undef LOG_TAG
37 #define LOG_TAG "Util"
38
39 namespace OHOS {
40 namespace Msdp {
41 namespace DeviceStatus {
42 namespace {
43 constexpr size_t BUF_TID_SIZE { 10 };
44 constexpr size_t PROGRAM_NAME_SIZE { 256 };
45 constexpr size_t BUF_CMD_SIZE { 512 };
46 constexpr uint32_t BASE_YEAR { 1900 };
47 constexpr uint32_t BASE_MON { 1 };
48 constexpr uint32_t MS_NS { 1000000 };
49 constexpr int32_t FILE_SIZE_MAX { 0x5000 };
50 constexpr size_t SHORT_KEY_LENGTH { 20 };
51 constexpr size_t PLAINTEXT_LENGTH { 4 };
52 constexpr int32_t ROTATE_POLICY_WINDOW_ROTATE { 0 };
53 constexpr int32_t ROTATE_POLICY_SCREEN_ROTATE { 1 };
54 constexpr int32_t ROTATE_POLICY_FOLD_MODE { 2 };
55 #ifndef OHOS_BUILD_ENABLE_ARKUI_X
56 const int32_t ROTATE_POLICY = OHOS::system::GetIntParameter("const.window.device.rotate_policy", 0);
57 const std::string FOLD_ROTATE_POLICY = OHOS::system::GetParameter("const.window.foldabledevice.rotate_policy", "0,0");
58 const std::string FOLD_SCREEN_TYPE = OHOS::system::GetParameter("const.window.foldscreen.type", "0,0,0,0");
59 const std::string SECONDARY_FOLD_DISPLAY = "6";
60 #endif // OHOS_BUILD_ENABLE_ARKUI_X
61 const std::string SVG_PATH { "/system/etc/device_status/drag_icon/" };
62 } // namespace
63
GetPid()64 int32_t GetPid()
65 {
66 return static_cast<int32_t>(getpid());
67 }
68
GetThisThreadIdOfString()69 static std::string GetThisThreadIdOfString()
70 {
71 thread_local std::string threadLocalId;
72 if (threadLocalId.empty()) {
73 long tid = syscall(SYS_gettid);
74 char buf[BUF_TID_SIZE] = { 0 };
75 const int32_t ret = sprintf_s(buf, BUF_TID_SIZE, "%06d", tid);
76 if (ret < 0) {
77 FI_HILOGE("Call sprintf_s failed, ret:%{public}d", ret);
78 return threadLocalId;
79 }
80 buf[BUF_TID_SIZE - 1] = '\0';
81 threadLocalId = buf;
82 }
83 return threadLocalId;
84 }
85
GetThisThreadId()86 uint64_t GetThisThreadId()
87 {
88 std::string threadId = GetThisThreadIdOfString();
89 uint64_t tid = std::stoull(threadId);
90 return tid;
91 }
92
GetMillisTime()93 int64_t GetMillisTime()
94 {
95 auto timeNow = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now());
96 auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow.time_since_epoch());
97 return tmp.count();
98 }
99
GetTimeStamp(std::string & startTime)100 void GetTimeStamp(std::string &startTime)
101 {
102 timespec curTime;
103 clock_gettime(CLOCK_REALTIME, &curTime);
104 struct tm *timeinfo = localtime(&(curTime.tv_sec));
105 CHKPV(timeinfo);
106 startTime.append(std::to_string(timeinfo->tm_year + BASE_YEAR)).append("-")
107 .append(std::to_string(timeinfo->tm_mon + BASE_MON)).append("-").append(std::to_string(timeinfo->tm_mday))
108 .append(" ").append(std::to_string(timeinfo->tm_hour)).append(":").append(std::to_string(timeinfo->tm_min))
109 .append(":").append(std::to_string(timeinfo->tm_sec)).append(".")
110 .append(std::to_string(curTime.tv_nsec / MS_NS));
111 }
112
SetThreadName(const std::string & name)113 void SetThreadName(const std::string &name)
114 {
115 #ifndef OHOS_BUILD_ENABLE_ARKUI_X
116 prctl(PR_SET_NAME, name.c_str());
117 #endif // OHOS_BUILD_ENABLE_ARKUI_X
118 }
119
StringToken(std::string & strs,const std::string & sep,std::string & token)120 static size_t StringToken(std::string &strs, const std::string &sep, std::string &token)
121 {
122 token = "";
123 if (strs.empty()) {
124 return strs.npos;
125 }
126 size_t seat = strs.npos;
127 size_t temp = 0;
128 for (auto &item : sep) {
129 temp = strs.find(item);
130 if (strs.npos != temp) {
131 seat = (std::min)(seat, temp);
132 }
133 }
134 if (strs.npos != seat) {
135 token = strs.substr(0, seat);
136 if (strs.npos != seat + 1) {
137 strs = strs.substr(seat + 1, strs.npos);
138 }
139 if (seat == 0) {
140 return StringToken(strs, sep, token);
141 }
142 } else {
143 token = strs;
144 strs = "";
145 }
146 return token.size();
147 }
148
StringSplit(const std::string & str,const std::string & sep,std::vector<std::string> & vecList)149 size_t StringSplit(const std::string &str, const std::string &sep, std::vector<std::string> &vecList)
150 {
151 size_t size = 0;
152 auto strs = str;
153 std::string token;
154 while (str.npos != (size = StringToken(strs, sep, token))) {
155 vecList.push_back(token);
156 }
157 return vecList.size();
158 }
159
StringPrintf(const char * format,...)160 std::string StringPrintf(const char *format, ...)
161 {
162 char space[1024] { 0 };
163
164 va_list ap;
165 va_start(ap, format);
166 std::string result;
167 int32_t ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
168 if (ret >= RET_OK && static_cast<size_t>(ret) < sizeof(space)) {
169 result = space;
170 } else {
171 FI_HILOGE("The buffer is overflow");
172 }
173 va_end(ap);
174 return result;
175 }
176
GetAnonyString(const std::string & value)177 std::string GetAnonyString(const std::string &value)
178 {
179 if (value.empty()) {
180 return "empty";
181 }
182 std::string anonyStr = "******";
183 std::string str;
184 size_t strLen = value.length();
185 if (strLen == 0) {
186 FI_HILOGE("strLen is 0, value will overflow");
187 return "empty";
188 } else if (strLen <= SHORT_KEY_LENGTH) {
189 str += value[0];
190 str += anonyStr;
191 str += value[strLen - 1];
192 } else {
193 str.append(value, 0, PLAINTEXT_LENGTH);
194 str += anonyStr;
195 str.append(value, strLen - PLAINTEXT_LENGTH, PLAINTEXT_LENGTH);
196 }
197 return str;
198 }
199
GetFileName(const std::string & path)200 static std::string GetFileName(const std::string &path)
201 {
202 size_t nPos = path.find_last_of('/');
203 if (path.npos == nPos) {
204 nPos = path.find_last_of('\\');
205 }
206 if (path.npos == nPos) {
207 return path;
208 }
209 return path.substr(nPos + 1, path.npos);
210 }
211
GetProgramName()212 const char* GetProgramName()
213 {
214 static char programName[PROGRAM_NAME_SIZE] = { 0 };
215 if (programName[0] != '\0') {
216 return programName;
217 }
218
219 char buf[BUF_CMD_SIZE] = { 0 };
220 int32_t ret = sprintf_s(buf, BUF_CMD_SIZE, "/proc/%d/cmdline", static_cast<int32_t>(getpid()));
221 if (ret == -1) {
222 FI_HILOGE("GetProcessInfo sprintf_s cmdline error");
223 return "";
224 }
225 FILE *fp = fopen(buf, "rb");
226 if (fp == nullptr) {
227 FI_HILOGE("The fp is nullptr, filename:%{public}s", buf);
228 return "";
229 }
230 static constexpr size_t bufLineSize = 512;
231 char bufLine[bufLineSize] = { 0 };
232 if ((fgets(bufLine, bufLineSize, fp) == nullptr)) {
233 FI_HILOGE("fgets failed");
234 if (fclose(fp) != 0) {
235 FI_HILOGW("Close file failed");
236 }
237 fp = nullptr;
238 return "";
239 }
240 if (fclose(fp) != 0) {
241 FI_HILOGW("Close file:%{public}s failed", buf);
242 }
243 fp = nullptr;
244
245 std::string tempName(bufLine);
246 tempName = GetFileName(tempName);
247 if (tempName.empty()) {
248 FI_HILOGE("tempName is empty");
249 return "";
250 }
251 size_t copySize = std::min(tempName.size(), PROGRAM_NAME_SIZE - 1);
252 if (copySize == 0) {
253 FI_HILOGE("The copySize is 0");
254 return "";
255 }
256 errno_t result = memcpy_s(programName, PROGRAM_NAME_SIZE, tempName.c_str(), copySize);
257 if (result != EOK) {
258 FI_HILOGE("memcpy_s failed");
259 return "";
260 }
261 FI_HILOGI("Get program name success, programName:%{public}s", programName);
262
263 return programName;
264 }
265
CheckFileExtendName(const std::string & filePath,const std::string & checkExtension)266 bool CheckFileExtendName(const std::string &filePath, const std::string &checkExtension)
267 {
268 std::string::size_type pos = filePath.find_last_of('.');
269 if (pos == std::string::npos) {
270 FI_HILOGE("File is not found extension");
271 return false;
272 }
273 return (filePath.substr(pos + 1, filePath.npos) == checkExtension);
274 }
275
IsValidPath(const std::string & rootDir,const std::string & filePath)276 bool IsValidPath(const std::string &rootDir, const std::string &filePath)
277 {
278 return (filePath.compare(0, rootDir.size(), rootDir) == 0);
279 }
280
IsValidSvgPath(const std::string & filePath)281 bool IsValidSvgPath(const std::string &filePath)
282 {
283 return IsValidPath(SVG_PATH, filePath);
284 }
285
IsValidSvgFile(const std::string & filePath)286 bool IsValidSvgFile(const std::string &filePath)
287 {
288 CALL_DEBUG_ENTER;
289 if (filePath.empty()) {
290 FI_HILOGE("FilePath is empty");
291 return false;
292 }
293 char realPath[PATH_MAX] = { 0 };
294 if (realpath(filePath.c_str(), realPath) == nullptr) {
295 FI_HILOGE("Realpath return nullptr, realPath:%{private}s", realPath);
296 return false;
297 }
298 #ifndef OHOS_BUILD_ENABLE_ARKUI_X
299 if (!IsValidSvgPath(realPath)) {
300 FI_HILOGE("File path invalid");
301 return false;
302 }
303 #endif // OHOS_BUILD_ENABLE_ARKUI_X
304 if (!Utility::DoesFileExist(realPath)) {
305 FI_HILOGE("File not exist");
306 return false;
307 }
308 if (!CheckFileExtendName(realPath, "svg")) {
309 FI_HILOGE("Unable to parse files other than svg format");
310 return false;
311 }
312 int32_t fileSize = Utility::GetFileSize(realPath);
313 if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
314 FI_HILOGE("File size out of read range");
315 return false;
316 }
317 return true;
318 }
319
IsNum(const std::string & str)320 bool IsNum(const std::string &str)
321 {
322 std::istringstream sin(str);
323 double num = 0.0;
324 return (sin >> num) && sin.eof();
325 }
326
GetRotatePolicy(bool & isScreenRotation,std::vector<std::string> & foldRotatePolicys)327 void GetRotatePolicy(bool &isScreenRotation, std::vector<std::string> &foldRotatePolicys)
328 {
329 #ifndef OHOS_BUILD_ENABLE_ARKUI_X
330 if (ROTATE_POLICY == ROTATE_POLICY_WINDOW_ROTATE) {
331 isScreenRotation = false;
332 return;
333 }
334 if (ROTATE_POLICY == ROTATE_POLICY_SCREEN_ROTATE) {
335 isScreenRotation = true;
336 return;
337 }
338 if (ROTATE_POLICY == ROTATE_POLICY_FOLD_MODE) {
339 isScreenRotation = false;
340 StringSplit(FOLD_ROTATE_POLICY, ",", foldRotatePolicys);
341 return;
342 }
343 #endif // OHOS_BUILD_ENABLE_ARKUI_X
344 }
345
StringSplit(const std::string & str,char delim)346 std::vector<std::string> StringSplit(const std::string& str, char delim)
347 {
348 #ifndef OHOS_BUILD_ENABLE_ARKUI_X
349 std::size_t previous = 0;
350 std::size_t current = str.find(delim);
351 std::vector<std::string> elems;
352 while (current != std::string::npos) {
353 if (current > previous) {
354 elems.push_back(str.substr(previous, current - previous));
355 }
356 previous = current + 1;
357 current = str.find(delim, previous);
358 }
359 if (previous != str.size()) {
360 elems.push_back(str.substr(previous));
361 }
362 return elems;
363 #endif // OHOS_BUILD_ENABLE_ARKUI_X
364 return {};
365 }
366
IsSecondaryDevice()367 bool IsSecondaryDevice()
368 {
369 #ifndef OHOS_BUILD_ENABLE_ARKUI_X
370 std::regex reg("^([0-9],){3}[0-9]{1}$");
371 if (!std::regex_match(FOLD_SCREEN_TYPE, reg)) {
372 return false;
373 }
374 std::vector<std::string> foldTypes = StringSplit(FOLD_SCREEN_TYPE, ',');
375 if (foldTypes.empty()) {
376 return false;
377 }
378 return foldTypes[0] == SECONDARY_FOLD_DISPLAY;
379 #endif // OHOS_BUILD_ENABLE_ARKUI_X
380 return false;
381 }
382
IsValidJsonPath(const std::string & filePath)383 bool IsValidJsonPath(const std::string &filePath)
384 {
385 return IsValidPath("/system/etc/multimodalinput/", filePath);
386 }
387
IsFileExists(const std::string & fileName)388 bool IsFileExists(const std::string &fileName)
389 {
390 return (access(fileName.c_str(), F_OK) == 0);
391 }
392
ReadFile(const std::string & filePath)393 std::string ReadFile(const std::string &filePath)
394 {
395 FILE *fp = fopen(filePath.c_str(), "r");
396 CHKPS(fp);
397 std::string dataStr;
398 char buf[256] = {};
399 while (fgets(buf, sizeof(buf), fp) != nullptr) {
400 dataStr += buf;
401 }
402 if (fclose(fp) != 0) {
403 FI_HILOGW("Close file failed");
404 }
405 return dataStr;
406 }
407
ReadJsonFile(const std::string & filePath)408 std::string ReadJsonFile(const std::string &filePath)
409 {
410 if (filePath.empty()) {
411 FI_HILOGE("FilePath is empty");
412 return "";
413 }
414 char realPath[PATH_MAX] = {};
415 CHKPS(realpath(filePath.c_str(), realPath));
416 if (!IsValidJsonPath(realPath)) {
417 FI_HILOGE("File path is error, filePath:%{private}s", realPath);
418 return "";
419 }
420 if (!CheckFileExtendName(realPath, "json")) {
421 FI_HILOGE("Unable to parse files other than json format");
422 return "";
423 }
424 if (!IsFileExists(realPath)) {
425 FI_HILOGE("File is not existent");
426 return "";
427 }
428 int32_t fileSize = Utility::GetFileSize(realPath);
429 if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
430 FI_HILOGE("File size out of read range");
431 return "";
432 }
433 return ReadFile(filePath);
434 }
435 } // namespace DeviceStatus
436 } // namespace Msdp
437 } // namespace OHOS