xref: /aosp_15_r20/external/cronet/base/process/internal_aix.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/process/internal_aix.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <sys/procfs.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <errno.h>
10*6777b538SAndroid Build Coastguard Worker #include <fcntl.h>
11*6777b538SAndroid Build Coastguard Worker #include <limits.h>
12*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include <map>
15*6777b538SAndroid Build Coastguard Worker #include <string>
16*6777b538SAndroid Build Coastguard Worker #include <vector>
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_split.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker // Not defined on AIX by default.
27*6777b538SAndroid Build Coastguard Worker #define NAME_MAX 255
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker namespace base {
30*6777b538SAndroid Build Coastguard Worker namespace internalAIX {
31*6777b538SAndroid Build Coastguard Worker 
32*6777b538SAndroid Build Coastguard Worker const char kProcDir[] = "/proc";
33*6777b538SAndroid Build Coastguard Worker 
34*6777b538SAndroid Build Coastguard Worker const char kStatFile[] = "psinfo";  // AIX specific
35*6777b538SAndroid Build Coastguard Worker 
GetProcPidDir(pid_t pid)36*6777b538SAndroid Build Coastguard Worker FilePath GetProcPidDir(pid_t pid) {
37*6777b538SAndroid Build Coastguard Worker   return FilePath(kProcDir).Append(NumberToString(pid));
38*6777b538SAndroid Build Coastguard Worker }
39*6777b538SAndroid Build Coastguard Worker 
ProcDirSlotToPid(const char * d_name)40*6777b538SAndroid Build Coastguard Worker pid_t ProcDirSlotToPid(const char* d_name) {
41*6777b538SAndroid Build Coastguard Worker   int i;
42*6777b538SAndroid Build Coastguard Worker   for (i = 0; i < NAME_MAX && d_name[i]; ++i) {
43*6777b538SAndroid Build Coastguard Worker     if (!IsAsciiDigit(d_name[i])) {
44*6777b538SAndroid Build Coastguard Worker       return 0;
45*6777b538SAndroid Build Coastguard Worker     }
46*6777b538SAndroid Build Coastguard Worker   }
47*6777b538SAndroid Build Coastguard Worker   if (i == NAME_MAX)
48*6777b538SAndroid Build Coastguard Worker     return 0;
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker   // Read the process's command line.
51*6777b538SAndroid Build Coastguard Worker   pid_t pid;
52*6777b538SAndroid Build Coastguard Worker   std::string pid_string(d_name);
53*6777b538SAndroid Build Coastguard Worker   if (!StringToInt(pid_string, &pid)) {
54*6777b538SAndroid Build Coastguard Worker     NOTREACHED();
55*6777b538SAndroid Build Coastguard Worker     return 0;
56*6777b538SAndroid Build Coastguard Worker   }
57*6777b538SAndroid Build Coastguard Worker   return pid;
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker 
ReadProcFile(const FilePath & file,struct psinfo * info)60*6777b538SAndroid Build Coastguard Worker bool ReadProcFile(const FilePath& file, struct psinfo* info) {
61*6777b538SAndroid Build Coastguard Worker   // Synchronously reading files in /proc is safe.
62*6777b538SAndroid Build Coastguard Worker   ScopedAllowBlocking scoped_allow_blocking;
63*6777b538SAndroid Build Coastguard Worker   int fileId;
64*6777b538SAndroid Build Coastguard Worker   if ((fileId = open(file.value().c_str(), O_RDONLY)) < 0) {
65*6777b538SAndroid Build Coastguard Worker     DPLOG(WARNING) << "Failed to open " << file.MaybeAsASCII();
66*6777b538SAndroid Build Coastguard Worker     return false;
67*6777b538SAndroid Build Coastguard Worker   }
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker   if (read(fileId, info, sizeof(*info)) < 0) {
70*6777b538SAndroid Build Coastguard Worker     DPLOG(WARNING) << "Failed to read " << file.MaybeAsASCII();
71*6777b538SAndroid Build Coastguard Worker     return false;
72*6777b538SAndroid Build Coastguard Worker   }
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker   return true;
75*6777b538SAndroid Build Coastguard Worker }
76*6777b538SAndroid Build Coastguard Worker 
ReadProcStats(pid_t pid,struct psinfo * info)77*6777b538SAndroid Build Coastguard Worker bool ReadProcStats(pid_t pid, struct psinfo* info) {
78*6777b538SAndroid Build Coastguard Worker   FilePath stat_file = internalAIX::GetProcPidDir(pid).Append(kStatFile);
79*6777b538SAndroid Build Coastguard Worker   return ReadProcFile(stat_file, info);
80*6777b538SAndroid Build Coastguard Worker }
81*6777b538SAndroid Build Coastguard Worker 
ParseProcStats(struct psinfo & stats_data,std::vector<std::string> * proc_stats)82*6777b538SAndroid Build Coastguard Worker bool ParseProcStats(struct psinfo& stats_data,
83*6777b538SAndroid Build Coastguard Worker                     std::vector<std::string>* proc_stats) {
84*6777b538SAndroid Build Coastguard Worker   // The stat file is formatted as:
85*6777b538SAndroid Build Coastguard Worker   // struct psinfo
86*6777b538SAndroid Build Coastguard Worker   // see -
87*6777b538SAndroid Build Coastguard Worker   // https://www.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.files/proc.htm
88*6777b538SAndroid Build Coastguard Worker   proc_stats->clear();
89*6777b538SAndroid Build Coastguard Worker   // PID.
90*6777b538SAndroid Build Coastguard Worker   proc_stats->push_back(NumberToString(stats_data.pr_pid));
91*6777b538SAndroid Build Coastguard Worker   // Process name without parentheses. // 1
92*6777b538SAndroid Build Coastguard Worker   proc_stats->push_back(stats_data.pr_fname);
93*6777b538SAndroid Build Coastguard Worker   // Process State (Not available)  // 2
94*6777b538SAndroid Build Coastguard Worker   proc_stats->push_back("0");
95*6777b538SAndroid Build Coastguard Worker   // Process id of parent  // 3
96*6777b538SAndroid Build Coastguard Worker   proc_stats->push_back(NumberToString(stats_data.pr_ppid));
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker   // Process group id // 4
99*6777b538SAndroid Build Coastguard Worker   proc_stats->push_back(NumberToString(stats_data.pr_pgid));
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker   return true;
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker typedef std::map<std::string, std::string> ProcStatMap;
ParseProcStat(const std::string & contents,ProcStatMap * output)105*6777b538SAndroid Build Coastguard Worker void ParseProcStat(const std::string& contents, ProcStatMap* output) {
106*6777b538SAndroid Build Coastguard Worker   StringPairs key_value_pairs;
107*6777b538SAndroid Build Coastguard Worker   SplitStringIntoKeyValuePairs(contents, ' ', '\n', &key_value_pairs);
108*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < key_value_pairs.size(); ++i) {
109*6777b538SAndroid Build Coastguard Worker     output->insert(key_value_pairs[i]);
110*6777b538SAndroid Build Coastguard Worker   }
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker 
GetProcStatsFieldAsInt64(const std::vector<std::string> & proc_stats,ProcStatsFields field_num)113*6777b538SAndroid Build Coastguard Worker int64_t GetProcStatsFieldAsInt64(const std::vector<std::string>& proc_stats,
114*6777b538SAndroid Build Coastguard Worker                                  ProcStatsFields field_num) {
115*6777b538SAndroid Build Coastguard Worker   DCHECK_GE(field_num, VM_PPID);
116*6777b538SAndroid Build Coastguard Worker   CHECK_LT(static_cast<size_t>(field_num), proc_stats.size());
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   int64_t value;
119*6777b538SAndroid Build Coastguard Worker   return StringToInt64(proc_stats[field_num], &value) ? value : 0;
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker 
GetProcStatsFieldAsSizeT(const std::vector<std::string> & proc_stats,ProcStatsFields field_num)122*6777b538SAndroid Build Coastguard Worker size_t GetProcStatsFieldAsSizeT(const std::vector<std::string>& proc_stats,
123*6777b538SAndroid Build Coastguard Worker                                 ProcStatsFields field_num) {
124*6777b538SAndroid Build Coastguard Worker   DCHECK_GE(field_num, VM_PPID);
125*6777b538SAndroid Build Coastguard Worker   CHECK_LT(static_cast<size_t>(field_num), proc_stats.size());
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker   size_t value;
128*6777b538SAndroid Build Coastguard Worker   return StringToSizeT(proc_stats[field_num], &value) ? value : 0;
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker 
ReadProcStatsAndGetFieldAsInt64(pid_t pid,ProcStatsFields field_num)131*6777b538SAndroid Build Coastguard Worker int64_t ReadProcStatsAndGetFieldAsInt64(pid_t pid, ProcStatsFields field_num) {
132*6777b538SAndroid Build Coastguard Worker   struct psinfo stats_data;
133*6777b538SAndroid Build Coastguard Worker   if (!ReadProcStats(pid, &stats_data))
134*6777b538SAndroid Build Coastguard Worker     return 0;
135*6777b538SAndroid Build Coastguard Worker   std::vector<std::string> proc_stats;
136*6777b538SAndroid Build Coastguard Worker   if (!ParseProcStats(stats_data, &proc_stats))
137*6777b538SAndroid Build Coastguard Worker     return 0;
138*6777b538SAndroid Build Coastguard Worker 
139*6777b538SAndroid Build Coastguard Worker   return GetProcStatsFieldAsInt64(proc_stats, field_num);
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker 
ReadProcStatsAndGetFieldAsSizeT(pid_t pid,ProcStatsFields field_num)142*6777b538SAndroid Build Coastguard Worker size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid, ProcStatsFields field_num) {
143*6777b538SAndroid Build Coastguard Worker   struct psinfo stats_data;
144*6777b538SAndroid Build Coastguard Worker   if (!ReadProcStats(pid, &stats_data))
145*6777b538SAndroid Build Coastguard Worker     return 0;
146*6777b538SAndroid Build Coastguard Worker   std::vector<std::string> proc_stats;
147*6777b538SAndroid Build Coastguard Worker   if (!ParseProcStats(stats_data, &proc_stats))
148*6777b538SAndroid Build Coastguard Worker     return 0;
149*6777b538SAndroid Build Coastguard Worker   return GetProcStatsFieldAsSizeT(proc_stats, field_num);
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker 
152*6777b538SAndroid Build Coastguard Worker }  // namespace internalAIX
153*6777b538SAndroid Build Coastguard Worker }  // namespace base
154