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