// 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"
#include "starboard/types.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 (size_t i = 0; i < other_stats.size(); ++i)
    proc_stats->push_back(other_stats[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 (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 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
