• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 "common_utils.h"
17 
18 #include <cstdint>
19 #include <cstdio>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <sstream>
23 #include <string>
24 #include <sys/wait.h>
25 #include <sys/syscall.h>
26 #include <unistd.h>
27 #include <vector>
28 
29 #include "securec.h"
30 #include "time_util.h"
31 
32 using namespace std;
33 namespace OHOS {
34 namespace HiviewDFX {
35 namespace CommonUtils {
36 namespace {
37 constexpr int32_t UID_TRANSFORM_DIVISOR = 200000;
GetProcessNameFromProcCmdline(int32_t pid)38 std::string GetProcessNameFromProcCmdline(int32_t pid)
39 {
40     std::string procCmdlinePath = "/proc/" + std::to_string(pid) + "/cmdline";
41     std::string procCmdlineContent = FileUtil::GetFirstLine(procCmdlinePath);
42     if (procCmdlineContent.empty()) {
43         return "";
44     }
45 
46     size_t procNameStartPos = 0;
47     size_t procNameEndPos = procCmdlineContent.size();
48     for (size_t i = 0; i < procCmdlineContent.size(); i++) {
49         if (procCmdlineContent[i] == '/') {
50             // for the format '/system/bin/hiview' of the cmdline file
51             procNameStartPos = i + 1; // 1 for next char
52         } else if (procCmdlineContent[i] == '\0') {
53             // for the format 'hiview \0 3 \0 hiview' of the cmdline file
54             procNameEndPos = i;
55             break;
56         }
57     }
58     return procCmdlineContent.substr(procNameStartPos, procNameEndPos - procNameStartPos);
59 }
60 
GetProcessNameFromProcStat(int32_t pid)61 std::string GetProcessNameFromProcStat(int32_t pid)
62 {
63     std::string procStatFilePath = "/proc/" + std::to_string(pid) + "/stat";
64     std::string procStatFileContent = FileUtil::GetFirstLine(procStatFilePath);
65     if (procStatFileContent.empty()) {
66         return "";
67     }
68     // for the format '40 (hiview) I ...'
69     auto procNameStartPos = procStatFileContent.find('(');
70     if (procNameStartPos == std::string::npos) {
71         return "";
72     }
73     procNameStartPos += 1; // 1: for '(' next char
74 
75     auto procNameEndPos = procStatFileContent.find(')');
76     if (procNameEndPos == std::string::npos) {
77         return "";
78     }
79     if (procNameEndPos <= procNameStartPos) {
80         return "";
81     }
82     return procStatFileContent.substr(procNameStartPos, procNameEndPos - procNameStartPos);
83 }
84 }
85 
GetProcNameByPid(pid_t pid)86 std::string GetProcNameByPid(pid_t pid)
87 {
88     std::string result;
89     char buf[BUF_SIZE_256] = {0};
90     (void)snprintf_s(buf, BUF_SIZE_256, BUF_SIZE_256 - 1, "/proc/%d/comm", pid);
91     FileUtil::LoadStringFromFile(std::string(buf, strlen(buf)), result);
92     auto pos = result.find_last_not_of(" \n\r\t");
93     if (pos == std::string::npos) {
94         return result;
95     }
96     result.erase(pos + 1);
97     return result;
98 }
99 
GetProcFullNameByPid(pid_t pid)100 std::string GetProcFullNameByPid(pid_t pid)
101 {
102     std::string procName = GetProcessNameFromProcCmdline(pid);
103     if (procName.empty() && errno != ESRCH) { // ESRCH means 'no such process'
104         procName = GetProcessNameFromProcStat(pid);
105     }
106     return procName;
107 }
108 
GetPidByName(const std::string & processName)109 pid_t GetPidByName(const std::string& processName)
110 {
111     pid_t pid = -1;
112     std::string cmd = "pidof " + processName;
113 
114     FILE* fp = popen(cmd.c_str(), "r");
115     if (fp != nullptr) {
116         char buffer[BUF_SIZE_256] = {'\0'};
117         while (fgets(buffer, sizeof(buffer) - 1, fp) != nullptr) {}
118         std::istringstream istr(buffer);
119         istr >> pid;
120         pclose(fp);
121     }
122     return pid;
123 }
124 
IsPidExist(pid_t pid)125 bool IsPidExist(pid_t pid)
126 {
127     std::string procDir = "/proc/" + std::to_string(pid);
128     return FileUtil::IsDirectory(procDir);
129 }
130 
IsSpecificCmdExist(const std::string & fullPath)131 bool IsSpecificCmdExist(const std::string& fullPath)
132 {
133     return access(fullPath.c_str(), X_OK) == 0;
134 }
135 
WriteCommandResultToFile(int fd,const std::string & cmd,const std::vector<std::string> & args)136 int WriteCommandResultToFile(int fd, const std::string &cmd, const std::vector<std::string> &args)
137 {
138     if (cmd.empty()) {
139         return -1;
140     }
141 
142     pid_t pid = fork();
143     if (pid < 0) {
144         return -1;
145     } else if (pid == 0) {
146         // follow standard, although dup2 may handle the case of invalid oldfd
147         if (fd >= 0) {
148             dup2(fd, STDOUT_FILENO);
149             dup2(fd, STDIN_FILENO);
150             dup2(fd, STDERR_FILENO);
151         }
152 
153         std::vector<char *> argv;
154         for (const auto &arg : args) {
155             argv.push_back(const_cast<char *>(arg.c_str()));
156         }
157         argv.push_back(0);
158         execv(cmd.c_str(), &argv[0]);
159     }
160 
161     constexpr uint64_t maxWaitingTime = 120; // 120 seconds
162     uint64_t endTime = TimeUtil::GetSteadyClockTimeMs() + maxWaitingTime * TimeUtil::SEC_TO_MILLISEC;
163     while (endTime > TimeUtil::GetSteadyClockTimeMs()) {
164         int status = 0;
165         pid_t p = waitpid(pid, &status, WNOHANG);
166         if (p < 0) {
167             return -1;
168         }
169 
170         if (p == pid) {
171             return WEXITSTATUS(status);
172         }
173     }
174 
175     return -1;
176 }
177 
GetTransformedUid(int32_t uid)178 int32_t GetTransformedUid(int32_t uid)
179 {
180     return uid / UID_TRANSFORM_DIVISOR;
181 }
182 }
183 } // namespace HiviewDFX
184 } // namespace OHOS
185