• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "util.h"
17 
18 #include <array>
19 #include <chrono>
20 #include <cinttypes>
21 #include <cstdarg>
22 #include <fstream>
23 
24 #include <sys/prctl.h>
25 #include <sys/stat.h>
26 #include <sys/syscall.h>
27 #include <sys/time.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 
31 #include "config_multimodal.h"
32 #include "define_multimodal.h"
33 #include "error_multimodal.h"
34 #include "mmi_log.h"
35 #include "securec.h"
36 
37 namespace OHOS {
38 namespace MMI {
39 namespace {
40 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "Util" };
41 constexpr int32_t FILE_SIZE_MAX = 0x6C445;
42 constexpr int32_t MAX_PRO_FILE_SIZE = 128000;
43 constexpr int32_t INVALID_FILE_SIZE = -1;
44 constexpr int32_t MIN_INTERVALTIME = 36;
45 constexpr int32_t MAX_INTERVALTIME = 100;
46 constexpr int32_t MIN_DELAYTIME = 300;
47 constexpr int32_t MAX_DELAYTIME = 1000;
48 constexpr int32_t COMMENT_SUBSCRIPT = 0;
49 const std::string CONFIG_ITEM_REPEAT = "Key.autorepeat";
50 const std::string CONFIG_ITEM_DELAY = "Key.autorepeat.delaytime";
51 const std::string CONFIG_ITEM_INTERVAL = "Key.autorepeat.intervaltime";
52 const std::string CONFIG_ITEM_TYPE = "Key.keyboard.type";
53 const std::string CURSORSTYLE_PATH = "/system/etc/multimodalinput/mouse_icon/";
54 const std::string DATA_PATH = "/data";
55 const std::string INPUT_PATH = "/system/";
56 const std::string KEY_PATH = "/vendor/etc/keymap/";
57 constexpr size_t BUF_TID_SIZE = 10;
58 constexpr size_t BUF_CMD_SIZE = 512;
59 constexpr size_t PROGRAM_NAME_SIZE = 256;
60 } // namespace
61 
GetSysClockTime()62 int64_t GetSysClockTime()
63 {
64     struct timespec ts = { 0, 0 };
65     if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
66         MMI_HILOGD("clock_gettime failed:%{public}d", errno);
67         return 0;
68     }
69     return (ts.tv_sec * 1000 * 1000) + (ts.tv_nsec / 1000);
70 }
71 
GetMillisTime()72 int64_t GetMillisTime()
73 {
74     auto timeNow = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now());
75     auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow.time_since_epoch());
76     return tmp.count();
77 }
78 
GetThisThreadIdOfString()79 static std::string GetThisThreadIdOfString()
80 {
81     thread_local std::string threadLocalId;
82     if (threadLocalId.empty()) {
83         long tid = syscall(SYS_gettid);
84         char buf[BUF_TID_SIZE] = {};
85         const int32_t ret = sprintf_s(buf, BUF_TID_SIZE, "%06d", tid);
86         if (ret < 0) {
87             printf("ERR: in %s, #%d, call sprintf_s failed, ret = %d.", __func__, __LINE__, ret);
88             return threadLocalId;
89         }
90         buf[BUF_TID_SIZE - 1] = '\0';
91         threadLocalId = buf;
92     }
93 
94     return threadLocalId;
95 }
96 
GetThisThreadId()97 uint64_t GetThisThreadId()
98 {
99     std::string stid = GetThisThreadIdOfString();
100     auto tid = std::stoull(stid);
101     return tid;
102 }
103 
StringToken(std::string & str,const std::string & sep,std::string & token)104 static size_t StringToken(std::string &str, const std::string &sep, std::string &token)
105 {
106     token = "";
107     if (str.empty()) {
108         return str.npos;
109     }
110     size_t pos = str.npos;
111     size_t tmp = 0;
112     for (auto &item : sep) {
113         tmp = str.find(item);
114         if (str.npos != tmp) {
115             pos = (std::min)(pos, tmp);
116         }
117     }
118     if (str.npos != pos) {
119         token = str.substr(0, pos);
120         if (str.npos != pos + 1) {
121             str = str.substr(pos + 1, str.npos);
122         }
123         if (pos == 0) {
124             return StringToken(str, sep, token);
125         }
126     } else {
127         token = str;
128         str = "";
129     }
130     return token.size();
131 }
132 
StringSplit(const std::string & str,const std::string & sep,std::vector<std::string> & vecList)133 size_t StringSplit(const std::string &str, const std::string &sep, std::vector<std::string> &vecList)
134 {
135     size_t size;
136     auto strs = str;
137     std::string token;
138     while (str.npos != (size = StringToken(strs, sep, token))) {
139         vecList.push_back(token);
140     }
141     return vecList.size();
142 }
143 
IdsListToString(const std::vector<int32_t> & list,const std::string & sep)144 std::string IdsListToString(const std::vector<int32_t> &list, const std::string &sep)
145 {
146     std::string str;
147     for (const auto &it : list) {
148         str += std::to_string(it) + sep;
149     }
150     if (str.size() > 0) {
151         str.resize(str.size() - sep.size());
152     }
153     return str;
154 }
155 
GetPid()156 int32_t GetPid()
157 {
158     return static_cast<int32_t>(getpid());
159 }
160 
GetFileName(const std::string & strPath)161 static std::string GetFileName(const std::string &strPath)
162 {
163     size_t nPos = strPath.find_last_of('/');
164     if (strPath.npos == nPos) {
165         nPos = strPath.find_last_of('\\');
166     }
167     if (strPath.npos == nPos) {
168         return strPath;
169     }
170 
171     return strPath.substr(nPos + 1, strPath.npos);
172 }
173 
GetProgramName()174 const char *GetProgramName()
175 {
176     static char programName[PROGRAM_NAME_SIZE] = {};
177     if (programName[0] != '\0') {
178         return programName;
179     }
180 
181     char buf[BUF_CMD_SIZE] = { 0 };
182     if (sprintf_s(buf, BUF_CMD_SIZE, "/proc/%d/cmdline", static_cast<int32_t>(getpid())) == -1) {
183         KMSG_LOGE("GetProcessInfo sprintf_s /proc/.../cmdline error");
184         return "";
185     }
186     FILE *fp = fopen(buf, "rb");
187     if (fp == nullptr) {
188         KMSG_LOGE("The fp is nullptr, filename = %s.", buf);
189         return "";
190     }
191     static constexpr size_t bufLineSize = 512;
192     char bufLine[bufLineSize] = { 0 };
193     if ((fgets(bufLine, bufLineSize, fp) == nullptr)) {
194         KMSG_LOGE("fgets failed.");
195         if (fclose(fp) != 0) {
196             KMSG_LOGW("Close file:%s failed", buf);
197         }
198         fp = nullptr;
199         return "";
200     }
201     if (fclose(fp) != 0) {
202         KMSG_LOGW("Close file:%s failed", buf);
203     }
204     fp = nullptr;
205 
206     std::string tempName(bufLine);
207     tempName = GetFileName(tempName);
208     if (tempName.empty()) {
209         KMSG_LOGE("tempName is empty.");
210         return "";
211     }
212     const size_t copySize = std::min(tempName.size(), PROGRAM_NAME_SIZE - 1);
213     if (copySize == 0) {
214         KMSG_LOGE("The copySize is 0.");
215         return "";
216     }
217     errno_t ret = memcpy_s(programName, PROGRAM_NAME_SIZE, tempName.c_str(), copySize);
218     if (ret != EOK) {
219         return "";
220     }
221     KMSG_LOGI("GetProgramName success. programName = %s", programName);
222 
223     return programName;
224 }
225 
SetThreadName(const std::string & name)226 void SetThreadName(const std::string &name)
227 {
228     prctl(PR_SET_NAME, name.c_str());
229 }
230 
IsFileExists(const std::string & fileName)231 static bool IsFileExists(const std::string &fileName)
232 {
233     return (access(fileName.c_str(), F_OK) == 0);
234 }
235 
CheckFileExtendName(const std::string & filePath,const std::string & checkExtension)236 static bool CheckFileExtendName(const std::string &filePath, const std::string &checkExtension)
237 {
238     std::string::size_type pos = filePath.find_last_of('.');
239     if (pos == std::string::npos) {
240         MMI_HILOGE("File is not find extension");
241         return false;
242     }
243     return (filePath.substr(pos + 1, filePath.npos) == checkExtension);
244 }
245 
GetFileSize(const std::string & filePath)246 static int32_t GetFileSize(const std::string &filePath)
247 {
248     struct stat statbuf = { 0 };
249     if (stat(filePath.c_str(), &statbuf) != 0) {
250         MMI_HILOGE("Get file size error");
251         return INVALID_FILE_SIZE;
252     }
253     return statbuf.st_size;
254 }
255 
ReadFile(const std::string & filePath)256 static std::string ReadFile(const std::string &filePath)
257 {
258     FILE *fp = fopen(filePath.c_str(), "r");
259     CHKPS(fp);
260     std::string dataStr;
261     char buf[256] = {};
262     while (fgets(buf, sizeof(buf), fp) != nullptr) {
263         dataStr += buf;
264     }
265     if (fclose(fp) != 0) {
266         MMI_HILOGW("Close file failed");
267     }
268     return dataStr;
269 }
270 
IsValidPath(const std::string & rootDir,const std::string & filePath)271 static bool IsValidPath(const std::string &rootDir, const std::string &filePath)
272 {
273     return (filePath.compare(0, rootDir.size(), rootDir) == 0);
274 }
275 
IsValidJsonPath(const std::string & filePath)276 bool IsValidJsonPath(const std::string &filePath)
277 {
278     return IsValidPath(DATA_PATH, filePath) || IsValidPath(INPUT_PATH, filePath);
279 }
280 
IsValidProPath(const std::string & filePath)281 static bool IsValidProPath(const std::string &filePath)
282 {
283     return IsValidPath(KEY_PATH, filePath);
284 }
285 
IsValidTomlPath(const std::string & filePath)286 static bool IsValidTomlPath(const std::string &filePath)
287 {
288     return IsValidPath(KEY_PATH, filePath);
289 }
290 
ReadProFile(const std::string & filePath,int32_t deviceId,std::map<int32_t,std::map<int32_t,int32_t>> & configMap)291 void ReadProFile(const std::string &filePath, int32_t deviceId,
292     std::map<int32_t, std::map<int32_t, int32_t>> &configMap)
293 {
294     CALL_DEBUG_ENTER;
295     if (filePath.empty()) {
296         MMI_HILOGE("FilePath is empty");
297         return;
298     }
299     char realPath[PATH_MAX] = {};
300     if (realpath(filePath.c_str(), realPath) == nullptr) {
301         MMI_HILOGI("The realpath return nullptr");
302         return;
303     }
304     if (!IsValidProPath(realPath)) {
305         MMI_HILOGE("File path is error");
306         return;
307     }
308     if (!IsFileExists(realPath)) {
309         MMI_HILOGE("File is not existent");
310         return;
311     }
312     if (!CheckFileExtendName(realPath, "pro")) {
313         MMI_HILOGE("Unable to parse files other than json format");
314         return;
315     }
316     auto fileSize = GetFileSize(realPath);
317     if ((fileSize == INVALID_FILE_SIZE) || (fileSize >= MAX_PRO_FILE_SIZE)) {
318         MMI_HILOGE("The configuration file size is incorrect");
319         return;
320     }
321     ReadProConfigFile(realPath, deviceId, configMap);
322 }
323 
IsNum(const std::string & str)324 static inline bool IsNum(const std::string &str)
325 {
326     std::istringstream sin(str);
327     double num;
328     return (sin >> num) && sin.eof();
329 }
330 
ReadProConfigFile(const std::string & realPath,int32_t deviceId,std::map<int32_t,std::map<int32_t,int32_t>> & configKey)331 void ReadProConfigFile(const std::string &realPath, int32_t deviceId,
332     std::map<int32_t, std::map<int32_t, int32_t>> &configKey)
333 {
334     CALL_DEBUG_ENTER;
335     std::ifstream reader(realPath);
336     if (!reader.is_open()) {
337         MMI_HILOGE("Failed to open config file");
338         return;
339     }
340     std::string strLine;
341     int32_t sysKeyValue;
342     int32_t nativeKeyValue;
343     int32_t elementKey = 0;
344     int32_t elementValue = 0;
345     std::map<int32_t, int32_t> tmpConfigKey;
346     while (std::getline(reader, strLine)) {
347         const char* line = strLine.c_str();
348         int32_t len = strlen(line);
349         char* realLine = static_cast<char*>(malloc(len + 1));
350         if (realLine == nullptr) {
351             MMI_HILOGE("Malloc failed");
352             return;
353         }
354         if (strcpy_s(realLine, len + 1, line) != EOK) {
355             MMI_HILOGE("strcpy_s error");
356             free(realLine);
357             realLine = nullptr;
358             return;
359         }
360         *(realLine + len + 1) = '\0';
361         int32_t ret = ReadConfigInfo(realLine, len, &elementKey, &elementValue);
362         free(realLine);
363         realLine = nullptr;
364         if (ret != RET_OK) {
365             MMI_HILOGE("Failed to read from line of config info");
366             reader.close();
367             return;
368         }
369         nativeKeyValue = elementKey;
370         sysKeyValue = elementValue;
371         MMI_HILOGD("The nativeKeyValue is:%{public}d, sysKeyValue is:%{public}d", nativeKeyValue, sysKeyValue);
372         tmpConfigKey.insert(std::pair<int32_t, int32_t>(nativeKeyValue, sysKeyValue));
373     }
374     reader.close();
375     auto iter = configKey.insert(std::make_pair(deviceId, tmpConfigKey));
376     if (!iter.second) {
377         MMI_HILOGE("The file name is duplicated");
378         return;
379     }
380 }
381 
ReadJsonFile(const std::string & filePath)382 std::string ReadJsonFile(const std::string &filePath)
383 {
384     if (filePath.empty()) {
385         MMI_HILOGE("FilePath is empty");
386         return "";
387     }
388     char realPath[PATH_MAX] = {};
389     if (realpath(filePath.c_str(), realPath) == nullptr) {
390         MMI_HILOGE("Path is error");
391         return "";
392     }
393     if (!IsValidJsonPath(realPath)) {
394         MMI_HILOGE("File path is error");
395         return "";
396     }
397     if (!CheckFileExtendName(realPath, "json")) {
398         MMI_HILOGE("Unable to parse files other than json format");
399         return "";
400     }
401     if (!IsFileExists(realPath)) {
402         MMI_HILOGE("File is not existent");
403         return "";
404     }
405     int32_t fileSize = GetFileSize(realPath);
406     if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
407         MMI_HILOGE("File size out of read range");
408         return "";
409     }
410     return ReadFile(filePath);
411 }
412 
ConfigItemSwitch(const std::string & configItem,const std::string & value,DeviceConfig & devConf)413 static int32_t ConfigItemSwitch(const std::string &configItem, const std::string &value, DeviceConfig &devConf)
414 {
415     CALL_DEBUG_ENTER;
416     if (configItem.empty() || value.empty()) {
417         MMI_HILOGE("Get key config item is invalid");
418         return RET_ERR;
419     }
420     if (!IsNum(value)) {
421         MMI_HILOGE("Get key config item is invalid");
422         return RET_ERR;
423     }
424     if (configItem == CONFIG_ITEM_REPEAT) {
425         devConf.autoSwitch = stoi(value);
426     } else if (configItem == CONFIG_ITEM_DELAY) {
427         devConf.delayTime = stoi(value);
428         if (devConf.delayTime < MIN_DELAYTIME || devConf.delayTime > MAX_DELAYTIME) {
429             MMI_HILOGE("Unusual the delaytime");
430             return RET_ERR;
431         }
432     } else if (configItem == CONFIG_ITEM_INTERVAL) {
433         devConf.intervalTime = stoi(value);
434         if (devConf.intervalTime < MIN_INTERVALTIME || devConf.intervalTime > MAX_INTERVALTIME) {
435             MMI_HILOGE("Unusual the intervaltime");
436             return RET_ERR;
437         }
438     } else if (configItem == CONFIG_ITEM_TYPE) {
439         devConf.keyboardType = stoi(value);
440     }
441     return RET_OK;
442 }
443 
ReadConfigFile(const std::string & realPath,DeviceConfig & devConf)444 static int32_t ReadConfigFile(const std::string &realPath, DeviceConfig &devConf)
445 {
446     CALL_DEBUG_ENTER;
447     std::ifstream cfgFile(realPath);
448     if (!cfgFile.is_open()) {
449         MMI_HILOGE("Failed to open config file");
450         return FILE_OPEN_FAIL;
451     }
452     std::string tmp;
453     while (std::getline(cfgFile, tmp)) {
454         RemoveSpace(tmp);
455         size_t pos = tmp.find('#');
456         if (pos != tmp.npos && pos != COMMENT_SUBSCRIPT) {
457             MMI_HILOGE("File format is error");
458             cfgFile.close();
459             return RET_ERR;
460         }
461         if (tmp.empty() || tmp.front() == '#') {
462             continue;
463         }
464         pos = tmp.find('=');
465         if (pos == (tmp.size() - 1) || pos == tmp.npos) {
466             MMI_HILOGE("Find config item error");
467             cfgFile.close();
468             return RET_ERR;
469         }
470         std::string configItem = tmp.substr(0, pos);
471         std::string value = tmp.substr(pos + 1);
472         if (ConfigItemSwitch(configItem, value, devConf) == RET_ERR) {
473             MMI_HILOGE("Configuration item error");
474             cfgFile.close();
475             return RET_ERR;
476         }
477     }
478     cfgFile.close();
479     return RET_OK;
480 }
481 
ReadTomlFile(const std::string & filePath,DeviceConfig & devConf)482 int32_t ReadTomlFile(const std::string &filePath, DeviceConfig &devConf)
483 {
484     if (filePath.empty()) {
485         MMI_HILOGE("FilePath is empty");
486         return RET_ERR;
487     }
488     char realPath[PATH_MAX] = {};
489     if (realpath(filePath.c_str(), realPath) == nullptr) {
490         MMI_HILOGI("The realpath return nullptr");
491         return RET_ERR;
492     }
493     if (!IsValidTomlPath(realPath)) {
494         MMI_HILOGE("File path is error");
495         return RET_ERR;
496     }
497     if (!IsFileExists(realPath)) {
498         MMI_HILOGE("File is not existent");
499         return RET_ERR;
500     }
501     if (!CheckFileExtendName(realPath, "TOML")) {
502         MMI_HILOGE("Unable to parse files other than json format");
503         return RET_ERR;
504     }
505     int32_t fileSize = GetFileSize(realPath);
506     if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
507         MMI_HILOGE("File size out of read range");
508         return RET_ERR;
509     }
510     if (ReadConfigFile(realPath, devConf) == RET_ERR) {
511         MMI_HILOGE("Read device config file failed");
512         return RET_ERR;
513     }
514     return RET_OK;
515 }
516 
ReadCursorStyleFile(const std::string & filePath)517 int32_t ReadCursorStyleFile(const std::string &filePath)
518 {
519     CALL_DEBUG_ENTER;
520     if (filePath.empty()) {
521         MMI_HILOGE("FilePath is empty");
522         return RET_ERR;
523     }
524     if (!IsFileExists(filePath)) {
525         MMI_HILOGE("File is not existent");
526         return RET_ERR;
527     }
528     char realPath[PATH_MAX] = {};
529     if (realpath(filePath.c_str(), realPath) == nullptr) {
530         MMI_HILOGE("Path is error");
531         return RET_ERR;
532     }
533     int32_t fileSize = GetFileSize(realPath);
534     if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
535         MMI_HILOGE("File size out of read range");
536         return RET_ERR;
537     }
538     return RET_OK;
539 }
540 
StringPrintf(const char * format,...)541 std::string StringPrintf(const char *format, ...)
542 {
543     char space[1024];
544 
545     va_list ap;
546     va_start(ap, format);
547     std::string result;
548     int32_t ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
549     if (ret >= RET_OK && (size_t)ret < sizeof(space)) {
550         result = space;
551     } else {
552         MMI_HILOGE("The buffer is overflow");
553     }
554     va_end(ap);
555     return result;
556 }
557 
FileVerification(std::string & filePath,const std::string & checkExtension)558 std::string FileVerification(std::string &filePath, const std::string &checkExtension)
559 {
560     if (filePath.empty()) {
561         MMI_HILOGE("FilePath is empty");
562         return "";
563     }
564     char realPath[PATH_MAX] = {};
565     if (realpath(filePath.c_str(), realPath) == nullptr) {
566         MMI_HILOGI("The realpath return nullptr");
567         return "";
568     }
569     if (!IsFileExists(realPath)) {
570         MMI_HILOGE("File is not existent");
571         return "";
572     }
573     if (!CheckFileExtendName(realPath, checkExtension)) {
574         MMI_HILOGE("Unable to parse files other than json format");
575         return "";
576     }
577     int32_t fileSize = GetFileSize(realPath);
578     if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
579         MMI_HILOGE("File size out of read range");
580         return "";
581     }
582     return realPath;
583 }
584 } // namespace MMI
585 } // namespace OHOS
586