1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
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 "common.h"
17#include <fcntl.h>
18#include <array>
19#include <cinttypes>
20#include <csignal>
21#include <dirent.h>
22#include <fstream>
23#include <iostream>
24#include <parameter.h>
25#include <parameters.h>
26#include <sstream>
27#include <sys/file.h>
28#include <sys/types.h>
29#include <sys/wait.h>
30#include <unistd.h>
31#include <sys/stat.h>
32
33#include "application_info.h"
34#include "bundle_mgr_proxy.h"
35#include "file_ex.h"
36#include "iservice_registry.h"
37#include "logging.h"
38#include "system_ability_definition.h"
39#include "os_account_info.h"
40#include "os_account_manager.h"
41
42using namespace OHOS;
43using namespace OHOS::AppExecFwk;
44namespace COMMON {
45namespace {
46const std::map<std::string, clockid_t> clockIdMap = {
47    {"realtime",            CLOCK_REALTIME},
48    {"mono",                CLOCK_MONOTONIC},
49    {"process_cputime_id",  CLOCK_PROCESS_CPUTIME_ID},
50    {"thread_cputime_id",   CLOCK_THREAD_CPUTIME_ID},
51    {"mono_raw",            CLOCK_MONOTONIC_RAW},
52    {"realtime_coarse",     CLOCK_REALTIME_COARSE},
53    {"mono_coarse",         CLOCK_MONOTONIC_COARSE},
54    {"boot",                CLOCK_BOOTTIME},
55    {"realtime_alarm",      CLOCK_REALTIME_ALARM},
56    {"boot_alarm",          CLOCK_BOOTTIME_ALARM},
57    {"sgi_cycle",           CLOCK_SGI_CYCLE},
58    {"tai",                 CLOCK_TAI},
59};
60constexpr int EXECVP_ERRNO = 2;
61const int SHELL_UID = 2000;
62const std::string DEFAULT_PATH = "/data/local/tmp/";
63constexpr int READ = 0;
64constexpr int WRITE = 1;
65const int FILE_PATH_SIZE = 512;
66const int BUFFER_SIZE = 1024;
67const int INVALID_PID = -1;
68constexpr int32_t EC_INVALID_VALUE = -2;
69const std::string KEY_HIVIEW_USER_TYPE = "const.logsystem.versiontype";
70const uint32_t MAX_CMD_ARGV = 50;
71const uint32_t MIN_CMD_ARGV = 2;
72const std::set<std::string> CMD_WHITE_LIST = {
73    "/system/bin/hiperf",    "/system/bin/hitrace",     "/system/bin/hisysevent",         "/system/bin/hidumper",
74    "/system/bin/SP_daemon", "/system/bin/hiprofilerd", "/system/bin/hiprofiler_plugins", "/system/bin/native_daemon",
75    "/system/bin/hilog"};
76}  // namespace
77
78bool IsProcessRunning(int& lockFileFd)
79{
80    setgid(SHELL_UID);
81    char buffer[PATH_MAX + 1] = {0};
82    readlink("/proc/self/exe", buffer, PATH_MAX);
83    std::string processName = buffer;
84    int pos = static_cast<int>(processName.find_last_of('/'));
85    if (pos != 0) {
86        processName = processName.substr(pos + 1, processName.size());
87    }
88
89    std::string fileName = DEFAULT_PATH + processName + ".pid";
90    umask(S_IWOTH);
91    int fd = open(fileName.c_str(), O_WRONLY | O_CREAT, static_cast<mode_t>(0664)); // 0664: rw-rw-r--
92    if (fd < 0) {
93        const int bufSize = 256;
94        char buf[bufSize] = {0};
95        strerror_r(errno, buf, bufSize);
96        PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, fileName.c_str(), errno, buf);
97        return false;
98    }
99    int flags = fcntl(fd, F_GETFD);
100    if (flags == -1) {
101        close(fd);
102        PROFILER_LOG_ERROR(LOG_CORE, "%s: get fd flags failed!", __func__);
103        return false;
104    }
105    flags |= FD_CLOEXEC;
106    if (fcntl(fd, F_SETFD, flags) == -1) {
107        close(fd);
108        PROFILER_LOG_ERROR(LOG_CORE, "%s: set fd_cloexec failed!", __func__);
109        return false;
110    }
111    if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
112        // 进程正在运行,加锁失败
113        close(fd);
114        printf("%s is running, please don't start it again.\n", processName.c_str());
115        PROFILER_LOG_ERROR(LOG_CORE, "%s is running, please don't start it again.", processName.c_str());
116        return true;
117    }
118    std::string pidStr = std::to_string(getpid());
119    auto nbytes = write(fd, pidStr.data(), pidStr.size());
120    lockFileFd = fd;
121    CHECK_TRUE(static_cast<size_t>(nbytes) == pidStr.size(), false, "write pid FAILED!");
122    return false;
123}
124
125bool IsProcessExist(const std::string& processName, int& pid)
126{
127    DIR* dir = opendir("/proc");
128    CHECK_NOTNULL(dir, false, "open /proc dir failed");
129    struct dirent* ptr;
130    int pidValue = INVALID_PID;
131    while ((ptr = readdir(dir)) != nullptr) {
132        if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
133            continue;
134        }
135        if ((!isdigit(*ptr->d_name)) || ptr->d_type != DT_DIR) {
136            continue;
137        }
138        char filePath[FILE_PATH_SIZE] = {0};
139        int len = snprintf_s(filePath, FILE_PATH_SIZE, FILE_PATH_SIZE - 1, "/proc/%s/cmdline", ptr->d_name);
140        if (len < 0) {
141            PROFILER_LOG_WARN(LOG_CORE, "maybe, the contents of cmdline had be cut off");
142            continue;
143        }
144        FILE* fp = fopen(filePath, "r");
145        if (fp == nullptr) {
146            PROFILER_LOG_DEBUG(LOG_CORE, "open file failed! %s", filePath);
147            continue;
148        }
149        char buf[BUFFER_SIZE] = {0};
150        if (fgets(buf, sizeof(buf) - 1, fp) == nullptr) {
151            fclose(fp);
152            continue;
153        }
154        std::string str(buf);
155        size_t found = str.rfind("/");
156        std::string fullProcess;
157        if (found != std::string::npos) {
158            fullProcess = str.substr(found + 1);
159        } else {
160            fullProcess = str;
161        }
162        if (fullProcess == processName) {
163            pidValue = atoi(ptr->d_name);
164            fclose(fp);
165            break;
166        }
167        fclose(fp);
168    }
169    closedir(dir);
170    if (pidValue != INVALID_PID) {
171        pid = pidValue;
172    }
173    return pidValue != INVALID_PID;
174}
175
176static void CloseStdio()
177{
178    close(STDIN_FILENO);
179    close(STDOUT_FILENO);
180    close(STDERR_FILENO);
181}
182
183int StartProcess(const std::string& processBin, std::vector<char*>& argv)
184{
185    if (argv.size() > MAX_CMD_ARGV || argv.size() < 1) {
186        PROFILER_LOG_ERROR(LOG_CORE, "%s: param invalid", __func__);
187        return -1;
188    }
189    // check whitelist
190    if (!CheckWhiteList(processBin)) {
191        PROFILER_LOG_ERROR(LOG_CORE, "%s: command not in whitelist!", __func__);
192        return -1;
193    }
194    for (auto& item : argv) {
195        std::string itemStr(item);
196        if (!CheckCmdLineArgValid(itemStr)) {
197            PROFILER_LOG_ERROR(LOG_CORE, "%s: command arg invalid : %s", __func__, itemStr.c_str());
198            return -1;
199        }
200    }
201    int pid = fork();
202    if (pid == 0) {
203        CloseStdio();
204        argv.push_back(nullptr); // last item in argv must be NULL
205        int retval = execv(processBin.data(), argv.data());
206        if (retval == -1 && errno == EXECVP_ERRNO) {
207            printf("warning: %s does not exist!\n", processBin.c_str());
208            PROFILER_LOG_WARN(LOG_CORE, "warning: %s does not exist!", processBin.c_str());
209        }
210        _exit(EXIT_FAILURE);
211    }
212
213    return pid;
214}
215
216int KillProcess(int pid)
217{
218    if (pid == -1) {
219        return -1;
220    }
221    int stat;
222    kill(pid, SIGTERM);
223    if (waitpid(pid, &stat, 0) == -1) {
224        if (errno != EINTR) {
225            stat = -1;
226        }
227    }
228    return stat;
229}
230
231void PrintMallinfoLog(const std::string& mallInfoPrefix, const struct mallinfo2& mi)
232{
233#ifdef HOOK_ENABLE
234    std::string mallinfoLog = mallInfoPrefix;
235    mallinfoLog += "arena = " + std::to_string(mi.arena) + ", ordblks = " + std::to_string(mi.ordblks);
236    mallinfoLog += ", smblks = " + std::to_string(mi.smblks) + ", hblks = " + std::to_string(mi.hblks);
237    mallinfoLog += ", hblkhd = " + std::to_string(mi.hblkhd) + ", usmblks = " + std::to_string(mi.usmblks);
238    mallinfoLog +=
239        ", fsmblks = " + std::to_string(mi.fsmblks) + ", uordblks = " + std::to_string(mi.uordblks);
240    mallinfoLog +=
241        ", fordblks = " + std::to_string(mi.fordblks) + ", keepcost = " + std::to_string(mi.keepcost);
242    PROFILER_LOG_INFO(LOG_CORE, "%s", mallinfoLog.c_str());
243#endif  // HOOK_ENABLE
244}
245
246bool GetDeveloperMode()
247{
248    bool developerMode = OHOS::system::GetBoolParameter("const.security.developermode.state", true);
249    if (!developerMode) {
250        PROFILER_LOG_INFO(LOG_CORE, "It is not developer mode!");
251    }
252    return developerMode;
253}
254
255inline int CustomFdClose(int& fd)
256{
257    int ret = close(fd);
258    if (ret == 0) {
259        fd = -1;
260    }
261    return ret;
262}
263
264inline int CustomFdFclose(FILE** fp)
265{
266    int ret = fclose(*fp);
267    if (ret == 0) {
268        *fp = nullptr;
269    }
270    return ret;
271}
272
273FILE* CustomPopen(const std::vector<std::string>& command, const char* type, int fds[],
274                  volatile pid_t& childPid, bool needUnblock)
275{
276    PROFILER_LOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__);
277    if (command.size() < MIN_CMD_ARGV || command.size() > MAX_CMD_ARGV || type == nullptr || strlen(type) != 1) {
278        PROFILER_LOG_ERROR(LOG_CORE, "%s: param invalid", __func__);
279        return nullptr;
280    }
281
282    // only allow "r" or "w"
283    if ((type[0] != 'r' && type[0] != 'w')) {
284        errno = EINVAL;
285        return  nullptr;
286    }
287    // check whitelist
288    if (!CheckWhiteList(command[0])) {
289        PROFILER_LOG_ERROR(LOG_CORE, "%s: command not in whitelist!", __func__);
290        return nullptr;
291    }
292    // check cmd arg valid
293    for (auto& item : command) {
294        if (!CheckCmdLineArgValid(item)) {
295            PROFILER_LOG_ERROR(LOG_CORE, "%s: command arg invalid : %s", __func__, item.c_str());
296            return nullptr;
297        }
298    }
299    CHECK_TRUE(pipe(fds) == 0, nullptr, "Pipe open failed!");
300    pid_t pid = fork();
301    if (pid == -1) {
302        perror("fork");
303        exit(1);
304    }
305
306    if (pid == 0) {
307        // execve : the last argv must be nullptr.
308        std::vector<char*> argv(command.size() + 1, nullptr);
309        for (size_t i = 0, cmdSize = command.size(); i < cmdSize; i++) {
310            argv[i] = const_cast<char*>(command[i].data());
311        }
312
313        if (strncmp(type, "r", strlen(type)) == 0) {
314            CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "CustomFdClose failed!");
315            dup2(fds[WRITE], STDOUT_FILENO); // Redirect stdout to pipe
316            CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "CustomFdClose failed!");
317        } else {
318            CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "CustomFdClose failed!");
319            dup2(fds[READ], STDIN_FILENO); // Redirect stdin to pipe
320            CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "CustomFdClose failed!");
321        }
322
323        setpgid(pid, pid);
324        // exe path = argv[0]; exe name = argv[1]
325        if (execv(argv[0], &argv[1]) == -1) {
326            PROFILER_LOG_ERROR(LOG_CORE, "execv failed {%s:%s}", __func__, strerror(errno));
327            exit(EXIT_FAILURE);
328        }
329    }
330
331    if (!needUnblock) {
332        if (strncmp(type, "r", strlen(type)) == 0) {
333            // Close the WRITE end of the pipe since parent's fd is read-only
334            CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "%s %d CustomFdClose failed! errno(%s)\n",
335                __func__, __LINE__, strerror(errno));
336        } else {
337            // Close the READ end of the pipe since parent's fd is write-only
338            CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "%s %d CustomFdClose failed! errno(%s)\n",
339                __func__, __LINE__, strerror(errno));
340        }
341    }
342
343    // Make sure the parent pipe reads and writes exist;CustomPUnblock will use.
344    childPid = pid;
345    if (strncmp(type, "r", strlen(type)) == 0) {
346        PROFILER_LOG_DEBUG(LOG_CORE, "END %s fds[READ]: success!", __func__);
347        return fdopen(fds[READ], "r");
348    }
349
350    PROFILER_LOG_DEBUG(LOG_CORE, "END %s fds[WRITE]: success!", __func__);
351    return fdopen(fds[WRITE], "w");
352}
353
354bool IsNumeric(const std::string& str)
355{
356    std::istringstream iss(str);
357    int number;
358    char trailingCharacter;
359    if (!(iss >> number)) {
360        return false;
361    }
362    if (iss >> trailingCharacter) {
363        return false;
364    }
365    return true;
366}
367
368int CustomPclose(FILE* fp, int fds[], volatile pid_t& childPid, bool needUnblock)
369{
370    PROFILER_LOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__);
371    CHECK_NOTNULL(fp, -1, "NOTE %s: fp is null", __func__);
372
373    int stat = 0;
374
375    if (needUnblock) {
376        PROFILER_LOG_DEBUG(LOG_CORE, "NOTE Kill Endless Loop Child %d.", childPid);
377        kill(childPid, SIGKILL);
378    }
379
380    while (waitpid(childPid, &stat, 0) == -1) {
381        PROFILER_LOG_ERROR(LOG_CORE, "%s: %s.", __func__, strerror(errno));
382        if (errno == EINTR) {
383            continue;
384        }
385        break;
386    }
387
388    if (needUnblock) {
389        if (fileno(fp) == fds[READ]) {
390            fds[READ] = -1;
391            if (CustomFdClose(fds[WRITE]) != 0) {
392                PROFILER_LOG_ERROR(LOG_CORE, "CustomFdClose failed!");
393                CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!");
394                return -1;
395            }
396        } else if (fileno(fp) == fds[WRITE]) {
397            fds[WRITE] = -1;
398            if (CustomFdClose(fds[READ]) != 0) {
399                PROFILER_LOG_ERROR(LOG_CORE, "CustomFdClose failed!");
400                CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!");
401                return -1;
402            }
403        } else {
404            PROFILER_LOG_INFO(LOG_CORE, "%s: Can't find fp in fds[READ/WRITE].", __func__);
405        }
406    }
407
408    CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!");
409
410    PROFILER_LOG_DEBUG(LOG_CORE, "END %s: success!", __func__);
411    return stat;
412}
413
414// IF pipe fds is block, before release other threads, you need call CustomPUnblock
415int CustomPUnblock(int fds[])
416{
417    PROFILER_LOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__);
418
419    CHECK_TRUE(fds[READ] != -1 && fds[WRITE] != -1, -1, "END fds[READ/WRITE]=-1");
420
421    int stat = fcntl(fds[READ], F_GETFL);
422    CHECK_TRUE(stat != -1, -1, "END fcntl(F_GETFL) failed!");
423
424    if (!(stat & O_NONBLOCK)) {
425        PROFILER_LOG_DEBUG(LOG_CORE, "NOTE %s: ready!Unblock r_fd and close all", __func__);
426        const char* eof = "\n\0";
427        write(fds[WRITE], eof, strlen(eof) + 1);
428        fcntl(fds[READ], F_SETFL, O_NONBLOCK);
429    }
430    PROFILER_LOG_DEBUG(LOG_CORE, "END %s: success!", __func__);
431    return 0;
432}
433
434int GetServicePort()
435{
436    const std::string portRangePath = "/proc/sys/net/ipv4/ip_local_port_range";
437    std::ifstream file(portRangePath.c_str());
438    CHECK_TRUE(file.is_open(), -1, "Open file failed! filePath:%s", portRangePath.c_str());
439
440    std::string rangeStr;
441    copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(rangeStr));
442
443    int minPort;
444    int maxPort;
445    std::istringstream istr(rangeStr);
446    istr >> minPort >> maxPort;
447    const int offset = 3168; // To be compatible with previously used port 50051;
448    int port = (minPort + maxPort) / 2 + offset;
449    PROFILER_LOG_DEBUG(LOG_CORE, "Service port is: %d", port);
450    return port;
451}
452
453void SplitString(const std::string& str, const std::string &sep, std::vector<std::string>& ret)
454{
455    if (str.empty()) {
456        PROFILER_LOG_ERROR(LOG_CORE, "The string splited is empty!");
457        return;
458    }
459    std::string::size_type beginPos = str.find_first_not_of(sep);
460    std::string::size_type findPos = 0;
461    while (beginPos != std::string::npos) {
462        findPos = str.find(sep, beginPos);
463        std::string tmp;
464        if (findPos != std::string::npos) {
465            tmp = str.substr(beginPos, findPos - beginPos);
466            beginPos = findPos + sep.length();
467        } else {
468            tmp = str.substr(beginPos);
469            beginPos = findPos;
470        }
471        if (!tmp.empty()) {
472            ret.push_back(tmp);
473            tmp.clear();
474        }
475    }
476}
477
478bool CheckApplicationPermission(int pid, const std::string& processName)
479{
480    std::string bundleName;
481    if (pid > 0) {
482        std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline";
483        if (!LoadStringFromFile(filePath, bundleName)) {
484            PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!");
485            return false;
486        }
487        bundleName.resize(strlen(bundleName.c_str()));
488    } else {
489        bundleName = processName;
490    }
491    auto pos = bundleName.find(":");
492    if (pos != std::string::npos) {
493        bundleName = bundleName.substr(0, pos);
494    }
495    CHECK_TRUE(!bundleName.empty(), false, "Pid or process name is illegal!");
496
497    sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
498    CHECK_NOTNULL(sam, false, "GetSystemAbilityManager failed!");
499    sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
500    CHECK_NOTNULL(remoteObject, false, "Get BundleMgr SA failed!");
501    sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject);
502    AppExecFwk::ApplicationInfo appInfo;
503    bool ret = proxy->GetApplicationInfo(bundleName, AppExecFwk::GET_APPLICATION_INFO_WITH_DISABLE,
504                                         AppExecFwk::Constants::ANY_USERID, appInfo);
505    if (!ret) {
506        PROFILER_LOG_ERROR(LOG_CORE, "GetApplicationInfo failed!");
507        return false;
508    }
509    return appInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG;
510}
511bool CheckApplicationEncryped(int pid, const std::string& processName)
512{
513    std::string bundleName;
514    if (pid > 0) {
515        std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline";
516        if (!LoadStringFromFile(filePath, bundleName)) {
517            PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!");
518            return false;
519        }
520        bundleName.resize(strlen(bundleName.c_str()));
521    } else {
522        bundleName = processName;
523    }
524    auto pos = bundleName.find(":");
525    if (pos != std::string::npos) {
526        bundleName = bundleName.substr(0, pos);
527    }
528    CHECK_TRUE(!bundleName.empty(), false, "Pid or process name is illegal!");
529    sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
530    CHECK_NOTNULL(sam, false, "GetSystemAbilityManager failed!");
531    sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
532    CHECK_NOTNULL(remoteObject, false, "Get BundleMgr SA failed!");
533    sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject);
534    AppExecFwk::ApplicationInfo appInfo;
535    bool ret = proxy->GetApplicationInfo(bundleName, AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO,
536                                         AppExecFwk::Constants::ANY_USERID, appInfo);
537    CHECK_TRUE(ret, false, "%s:%s GetApplicationInfo failed!", __func__, bundleName.c_str());
538    bool isEncrypted = (appInfo.applicationReservedFlag &
539                        static_cast<uint32_t>(AppExecFwk::ApplicationReservedFlag::ENCRYPTED_APPLICATION)) != 0;
540    PROFILER_LOG_INFO(LOG_CORE, "%s: check application encryped.%d : %s", __func__, isEncrypted, bundleName.c_str());
541    return isEncrypted;
542}
543
544bool VerifyPath(const std::string& filePath, const std::vector<std::string>& validPaths)
545{
546    if (validPaths.size() == 0) {
547        return true;
548    }
549
550    for (const std::string& path : validPaths) {
551        if (filePath.rfind(path, 0) == 0) {
552            return true;
553        }
554    }
555    return false;
556}
557
558const char* RealPath(std::string &filePath)
559{
560    if (filePath.size() > 0 && (filePath.back() == '/' || filePath.back() == '.')) {
561        return nullptr;
562    }
563    if (filePath.find('.') == std::string::npos) {
564        return filePath.c_str();
565    }
566    std::vector<std::string> paths;
567    SplitString(filePath, "/", paths);
568    std::vector<std::string> validPaths;
569    for (std::string& pathName: paths) {
570        if (pathName == "..") {
571            if (validPaths.size() == 0) {
572                return nullptr;
573            } else {
574                validPaths.pop_back();
575            }
576        } else {
577            validPaths.emplace_back(pathName);
578        }
579    }
580    filePath = "/";
581    for (const std::string &pathName : validPaths) {
582        filePath += pathName;
583        filePath += "/";
584    }
585    filePath.pop_back();
586    return filePath.c_str();
587}
588
589bool ReadFile(const std::string &filePath, const std::vector<std::string>& validPaths, std::string& fileContent)
590{
591    std::string pathName = filePath;
592    const char* realFilePath = RealPath(pathName);
593    CHECK_NOTNULL(realFilePath, false, "Fail to realPath: %s", filePath.c_str());
594
595    std::string realFilePathStr(realFilePath);
596    CHECK_TRUE(VerifyPath(realFilePathStr, validPaths), false, "Fail to VerifyPath: %s", realFilePathStr.c_str());
597
598    std::ifstream fileStream(realFilePathStr, std::ios::in);
599    CHECK_TRUE(fileStream.is_open(), false, "Fail to open file %s", realFilePathStr.c_str());
600
601    std::istreambuf_iterator<char> firstIt = { fileStream };
602    std::string content(firstIt, {});
603    fileContent = content;
604    return true;
605}
606
607bool IsUserMode()
608{
609    std::string debugMode = "0";
610    debugMode = OHOS::system::GetParameter("const.debuggable", debugMode);
611    if (debugMode != "0") {
612        PROFILER_LOG_INFO(LOG_CORE, "It is not user mode!");
613    }
614    return debugMode == "0";
615}
616
617std::string GetErrorMsg()
618{
619    const int bufSize = 256;
620    char buffer[bufSize] = { 0 };
621    strerror_r(errno, buffer, bufSize);
622    std::string errorMsg(buffer);
623    return errorMsg;
624}
625
626std::string GetTimeStr()
627{
628    time_t now = time(nullptr);
629    struct tm tmTime;
630    localtime_r(&now, &tmTime);
631
632    char buffer[32] = {0};
633    // 1900: count of years
634    (void)sprintf_s(buffer, sizeof(buffer), "%04d%02d%02d_%02d%02d%02d", tmTime.tm_year + 1900, tmTime.tm_mon + 1,
635        tmTime.tm_mday, tmTime.tm_hour, tmTime.tm_min, tmTime.tm_sec);
636    std::string timeStr(buffer);
637    return timeStr;
638}
639
640// get clockid by str, return CLOCK_REALTIME as default
641clockid_t GetClockId(const std::string& clockIdStr)
642{
643    clockid_t clockId = CLOCK_REALTIME;
644    auto iter = clockIdMap.find(clockIdStr);
645    if (iter != clockIdMap.end()) {
646        clockId = iter->second;
647    }
648    return clockId;
649}
650
651std::string GetClockStr(const int32_t clockId)
652{
653    std::string ret = "realtime";
654    for (const auto& [str, id] : clockIdMap) {
655        if (id == clockId) {
656            ret = str;
657            break;
658        }
659    }
660    return ret;
661}
662
663void AdaptSandboxPath(std::string& filePath, int pid)
664{
665    if (filePath.find("/data/storage") == 0 && access(filePath.c_str(), F_OK) != 0) {
666        filePath = "/proc/" + std::to_string(pid) + "/root" + filePath;
667    }
668}
669
670bool GetCurrentUserId(int32_t& userId)
671{
672    std::vector<int32_t> activeIds;
673    int32_t ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(activeIds);
674    if (ret != 0) {
675        PROFILER_LOG_ERROR(LOG_CORE, "QueryActiveOsAccountIds failed ret:%d", ret);
676        return false;
677    }
678
679    if (activeIds.empty()) {
680        PROFILER_LOG_ERROR(LOG_CORE, "QueryActiveOsAccountIds activeIds empty");
681        return false;
682    }
683    userId = activeIds[0];
684    PROFILER_LOG_INFO(LOG_CORE, "QueryActiveOsAccountIds userId[0]:%d", userId);
685    return true;
686}
687
688int32_t GetPackageUid(const std::string& name)
689{
690    int32_t userId = 0;
691    if (!GetCurrentUserId(userId)) {
692        PROFILER_LOG_ERROR(LOG_CORE, "Failed to get current user id");
693        return EC_INVALID_VALUE;
694    }
695    auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
696    if (manager == nullptr) {
697        PROFILER_LOG_ERROR(LOG_CORE, "systemAbilityManager is nullptr");
698        return EC_INVALID_VALUE;
699    }
700    sptr<IRemoteObject> remoteObject = manager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
701    if (remoteObject == nullptr) {
702        PROFILER_LOG_ERROR(LOG_CORE, "failed to get service id");
703        return EC_INVALID_VALUE;
704    }
705    sptr<AppExecFwk::IBundleMgr> mgr = iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
706    if (mgr == nullptr) {
707        PROFILER_LOG_ERROR(LOG_CORE, "mgr is nullptr");
708        return EC_INVALID_VALUE;
709    }
710    int32_t uid = mgr->GetUidByBundleName(name, userId);
711    PROFILER_LOG_INFO(LOG_CORE, "pkgname is: %s, uid is : %d", name.c_str(), uid);
712    return uid;
713}
714
715bool IsBetaVersion()
716{
717    int ret = static_cast<int>(FindParameter(KEY_HIVIEW_USER_TYPE.c_str()));
718    if (ret == -1) {
719        PROFILER_LOG_INFO(LOG_CORE, "user type is not exist");
720        return true;
721    }
722    std::string userType = OHOS::system::GetParameter(KEY_HIVIEW_USER_TYPE, "");
723    PROFILER_LOG_INFO(LOG_CORE, "user type is:%s", userType.c_str());
724    return userType == "beta";
725}
726
727std::pair<bool, std::string> CheckNotExistsFilePath(const std::string& filePath)
728{
729    size_t pos = filePath.rfind('/');
730    std::string pathDir = "";
731    if (pos != std::string::npos) {
732        pathDir = filePath.substr(0, pos);
733    } else {
734        pathDir = ".";
735    }
736    std::unique_ptr<char[]> pathDirRealPath = std::make_unique<char[]>(PATH_MAX);
737    if ((pathDir.length() >= PATH_MAX - 1) || (realpath(pathDir.c_str(), pathDirRealPath.get()) == nullptr)) {
738        PROFILER_LOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, pathDir.c_str(), errno);
739        return {false, ""};
740    }
741    if (access(pathDir.c_str(), F_OK) != 0) {
742        PROFILER_LOG_ERROR(LOG_CORE, "%s:Fail to access path: %s", __func__, pathDir.c_str());
743        return {false, ""};
744    }
745    return {true, std::string(pathDirRealPath.get()) + "/" + filePath.substr(pos + 1)};
746}
747
748bool CheckWhiteList(const std::string& cmdPath)
749{
750    if (cmdPath.empty()) {
751        PROFILER_LOG_ERROR(LOG_CORE, "cmd is empty {%s}", __func__);
752        return false;
753    }
754
755    if (CMD_WHITE_LIST.find(cmdPath) == CMD_WHITE_LIST.end() ||
756        cmdPath.find_first_of("|;&${}<>'\\!\n~?*%[]^") != std::string::npos) {
757        PROFILER_LOG_ERROR(LOG_CORE, "cmd %s:is illegal {%s}", cmdPath.c_str(), __func__);
758        return false;
759    }
760    return true;
761}
762
763bool CheckCmdLineArgValid(const std::string& cmdLine)
764{
765    if (cmdLine.empty()) {
766        PROFILER_LOG_ERROR(LOG_CORE, "cmdLine is empty {%s}", __func__);
767        return false;
768    }
769
770    if (cmdLine.find_first_of("|;&${}<>'\\!\n~?*%[]^") != std::string::npos) {
771        PROFILER_LOG_ERROR(LOG_CORE, "cmdLine %s is illegal {%s}", cmdLine.c_str(), __func__);
772        return false;
773    }
774    return true;
775}
776} // namespace COMMON
777