// 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_linux.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.
#if defined(OS_AIX)
#define NAME_MAX 255
#endif

namespace base {
namespace internal {

const char kProcDir[] = "/proc";

const char kStatFile[] = "stat";

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, std::string* buffer) {
  buffer->clear();
  // Synchronously reading files in /proc is safe.
  ThreadRestrictions::ScopedAllowIO allow_io;

  if (!ReadFileToString(file, buffer)) {
    DLOG(WARNING) << "Failed to read " << file.MaybeAsASCII();
    return false;
  }
  return !buffer->empty();
}

bool ReadProcStats(pid_t pid, std::string* buffer) {
  FilePath stat_file = internal::GetProcPidDir(pid).Append(kStatFile);
  return ReadProcFile(stat_file, buffer);
}

bool ParseProcStats(const std::string& stats_data,
                    std::vector<std::string>* proc_stats) {
  // |stats_data| may be empty if the process disappeared somehow.
  // e.g. http://crbug.com/145811
  if (stats_data.empty())
    return false;

  // The stat file is formatted as:
  // pid (process name) data1 data2 .... dataN
  // Look for the closing paren by scanning backwards, to avoid being fooled by
  // processes with ')' in the name.
  size_t open_parens_idx = stats_data.find(" (");
  size_t close_parens_idx = stats_data.rfind(") ");
  if (open_parens_idx == std::string::npos ||
      close_parens_idx == std::string::npos ||
      open_parens_idx > close_parens_idx) {
    DLOG(WARNING) << "Failed to find matched parens in '" << stats_data << "'";
    NOTREACHED();
    return false;
  }
  open_parens_idx++;

  proc_stats->clear();
  // PID.
  proc_stats->push_back(stats_data.substr(0, open_parens_idx));
  // Process name without parentheses.
  proc_stats->push_back(
      stats_data.substr(open_parens_idx + 1,
                        close_parens_idx - (open_parens_idx + 1)));

  // Split the rest.
  std::vector<std::string> other_stats = SplitString(
      stats_data.substr(close_parens_idx + 2), " ",
      base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  for (const auto& i : other_stats)
    proc_stats->push_back(i);
  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 (auto& i : key_value_pairs) {
    output->insert(std::move(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 ReadStatFileAndGetFieldAsInt64(const FilePath& stat_file,
                                       ProcStatsFields field_num) {
  std::string stats_data;
  if (!ReadProcFile(stat_file, &stats_data))
    return 0;
  std::vector<std::string> proc_stats;
  if (!ParseProcStats(stats_data, &proc_stats))
    return 0;
  return GetProcStatsFieldAsInt64(proc_stats, field_num);
}

int64_t ReadProcStatsAndGetFieldAsInt64(pid_t pid, ProcStatsFields field_num) {
  FilePath stat_file = internal::GetProcPidDir(pid).Append(kStatFile);
  return ReadStatFileAndGetFieldAsInt64(stat_file, field_num);
}

int64_t ReadProcSelfStatsAndGetFieldAsInt64(ProcStatsFields field_num) {
  FilePath stat_file = FilePath(kProcDir).Append("self").Append(kStatFile);
  return ReadStatFileAndGetFieldAsInt64(stat_file, field_num);
}

size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid,
                                       ProcStatsFields field_num) {
  std::string 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);
}

Time GetBootTime() {
  FilePath path("/proc/stat");
  std::string contents;
  if (!ReadProcFile(path, &contents))
    return Time();
  ProcStatMap proc_stat;
  ParseProcStat(contents, &proc_stat);
  ProcStatMap::const_iterator btime_it = proc_stat.find("btime");
  if (btime_it == proc_stat.end())
    return Time();
  int btime;
  if (!StringToInt(btime_it->second, &btime))
    return Time();
  return Time::FromTimeT(btime);
}

TimeDelta GetUserCpuTimeSinceBoot() {
  FilePath path("/proc/stat");
  std::string contents;
  if (!ReadProcFile(path, &contents))
    return TimeDelta();

  ProcStatMap proc_stat;
  ParseProcStat(contents, &proc_stat);
  ProcStatMap::const_iterator cpu_it = proc_stat.find("cpu");
  if (cpu_it == proc_stat.end())
    return TimeDelta();

  std::vector<std::string> cpu = SplitString(
      cpu_it->second, kWhitespaceASCII, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);

  if (cpu.size() < 2 || cpu[0] != "cpu")
    return TimeDelta();

  uint64_t user;
  uint64_t nice;
  if (!StringToUint64(cpu[0], &user) || !StringToUint64(cpu[1], &nice))
    return TimeDelta();

  return ClockTicksToTimeDelta(user + nice);
}

TimeDelta ClockTicksToTimeDelta(int clock_ticks) {
  // This queries the /proc-specific scaling factor which is
  // conceptually the system hertz.  To dump this value on another
  // system, try
  //   od -t dL /proc/self/auxv
  // and look for the number after 17 in the output; mine is
  //   0000040          17         100           3   134512692
  // which means the answer is 100.
  // It may be the case that this value is always 100.
  static const int kHertz = sysconf(_SC_CLK_TCK);

  return TimeDelta::FromMicroseconds(
      Time::kMicrosecondsPerSecond * clock_ticks / kHertz);
}

}  // namespace internal
}  // namespace base
