| Index: base/process/internal_aix.cc
|
| diff --git a/base/process/internal_aix.cc b/base/process/internal_aix.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7f03aee379d2336e2baead4cbe12c205073675b0
|
| --- /dev/null
|
| +++ b/base/process/internal_aix.cc
|
| @@ -0,0 +1,155 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/process/internal_aix.h"
|
| +
|
| +#include <sys/procfs.h>
|
| +
|
| +#include <errno.h>
|
| +#include <fcntl.h>
|
| +#include <limits.h>
|
| +#include <unistd.h>
|
| +
|
| +#include <map>
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "base/files/file_util.h"
|
| +#include "base/logging.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_split.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "base/threading/thread_restrictions.h"
|
| +#include "base/time/time.h"
|
| +
|
| +// Not defined on AIX by default.
|
| +#define NAME_MAX 255
|
| +
|
| +namespace base {
|
| +namespace internalAIX {
|
| +
|
| +const char kProcDir[] = "/proc";
|
| +
|
| +const char kStatFile[] = "psinfo"; // AIX specific
|
| +
|
| +FilePath GetProcPidDir(pid_t pid) {
|
| + return FilePath(kProcDir).Append(IntToString(pid));
|
| +}
|
| +
|
| +pid_t ProcDirSlotToPid(const char* d_name) {
|
| + int i;
|
| + for (i = 0; i < NAME_MAX && d_name[i]; ++i) {
|
| + if (!IsAsciiDigit(d_name[i])) {
|
| + return 0;
|
| + }
|
| + }
|
| + if (i == NAME_MAX)
|
| + return 0;
|
| +
|
| + // Read the process's command line.
|
| + pid_t pid;
|
| + std::string pid_string(d_name);
|
| + if (!StringToInt(pid_string, &pid)) {
|
| + NOTREACHED();
|
| + return 0;
|
| + }
|
| + return pid;
|
| +}
|
| +
|
| +bool ReadProcFile(const FilePath& file, struct psinfo* info) {
|
| + // Synchronously reading files in /proc is safe.
|
| + ThreadRestrictions::ScopedAllowIO allow_io;
|
| + int fileId;
|
| + if ((fileId = open(file.value().c_str(), O_RDONLY)) < 0) {
|
| + DLOG(WARNING) << "Failed to open " << file.MaybeAsASCII()
|
| + << " errno = " << errno;
|
| + return false;
|
| + }
|
| +
|
| + if (read(fileId, info, sizeof(*info)) < 0) {
|
| + DLOG(WARNING) << "Failed to read " << file.MaybeAsASCII()
|
| + << " errno = " << errno;
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool ReadProcStats(pid_t pid, struct psinfo* info) {
|
| + FilePath stat_file = internalAIX::GetProcPidDir(pid).Append(kStatFile);
|
| + return ReadProcFile(stat_file, info);
|
| +}
|
| +
|
| +bool ParseProcStats(struct psinfo& stats_data,
|
| + std::vector<std::string>* proc_stats) {
|
| + // The stat file is formatted as:
|
| + // struct psinfo
|
| + // see -
|
| + // https://www.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.files/proc.htm
|
| + proc_stats->clear();
|
| + // PID.
|
| + proc_stats->push_back(IntToString(stats_data.pr_pid));
|
| + // Process name without parentheses. // 1
|
| + proc_stats->push_back(stats_data.pr_fname);
|
| + // Process State (Not available) // 2
|
| + proc_stats->push_back("0");
|
| + // Process id of parent // 3
|
| + proc_stats->push_back(IntToString(stats_data.pr_ppid));
|
| +
|
| + // Process group id // 4
|
| + proc_stats->push_back(IntToString(stats_data.pr_pgid));
|
| +
|
| + return true;
|
| +}
|
| +
|
| +typedef std::map<std::string, std::string> ProcStatMap;
|
| +void ParseProcStat(const std::string& contents, ProcStatMap* output) {
|
| + StringPairs key_value_pairs;
|
| + SplitStringIntoKeyValuePairs(contents, ' ', '\n', &key_value_pairs);
|
| + for (size_t i = 0; i < key_value_pairs.size(); ++i) {
|
| + output->insert(key_value_pairs[i]);
|
| + }
|
| +}
|
| +
|
| +int64_t GetProcStatsFieldAsInt64(const std::vector<std::string>& proc_stats,
|
| + ProcStatsFields field_num) {
|
| + DCHECK_GE(field_num, VM_PPID);
|
| + CHECK_LT(static_cast<size_t>(field_num), proc_stats.size());
|
| +
|
| + int64_t value;
|
| + return StringToInt64(proc_stats[field_num], &value) ? value : 0;
|
| +}
|
| +
|
| +size_t GetProcStatsFieldAsSizeT(const std::vector<std::string>& proc_stats,
|
| + ProcStatsFields field_num) {
|
| + DCHECK_GE(field_num, VM_PPID);
|
| + CHECK_LT(static_cast<size_t>(field_num), proc_stats.size());
|
| +
|
| + size_t value;
|
| + return StringToSizeT(proc_stats[field_num], &value) ? value : 0;
|
| +}
|
| +
|
| +int64_t ReadProcStatsAndGetFieldAsInt64(pid_t pid, ProcStatsFields field_num) {
|
| + struct psinfo stats_data;
|
| + if (!ReadProcStats(pid, &stats_data))
|
| + return 0;
|
| + std::vector<std::string> proc_stats;
|
| + if (!ParseProcStats(stats_data, &proc_stats))
|
| + return 0;
|
| +
|
| + return GetProcStatsFieldAsInt64(proc_stats, field_num);
|
| +}
|
| +
|
| +size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid, ProcStatsFields field_num) {
|
| + struct psinfo stats_data;
|
| + if (!ReadProcStats(pid, &stats_data))
|
| + return 0;
|
| + std::vector<std::string> proc_stats;
|
| + if (!ParseProcStats(stats_data, &proc_stats))
|
| + return 0;
|
| + return GetProcStatsFieldAsSizeT(proc_stats, field_num);
|
| +}
|
| +
|
| +} // namespace internalAIX
|
| +} // namespace base
|
|
|