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