/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/profiling/common/proc_utils.h"

#include <sys/stat.h>
#include <unistd.h>

#include <cinttypes>

#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/profiling/normalize.h"

namespace perfetto {
namespace profiling {
namespace {

base::Optional<uint32_t> ParseProcStatusSize(const std::string& status,
                                             const std::string& key) {
  auto entry_idx = status.find(key);
  if (entry_idx == std::string::npos)
    return {};
  entry_idx = status.find_first_not_of(" \t", entry_idx + key.size());
  if (entry_idx == std::string::npos)
    return {};
  int32_t val = atoi(status.c_str() + entry_idx);
  if (val < 0) {
    PERFETTO_ELOG("Unexpected value reading %s", key.c_str());
    return {};
  }
  return static_cast<uint32_t>(val);
}
}  // namespace

base::Optional<std::vector<std::string>> NormalizeCmdlines(
    const std::vector<std::string>& cmdlines) {
  std::vector<std::string> normalized_cmdlines;
  normalized_cmdlines.reserve(cmdlines.size());

  for (size_t i = 0; i < cmdlines.size(); i++) {
    std::string cmdline = cmdlines[i];  // mutable copy
    // Add nullbyte to make sure it's a C string.
    cmdline.resize(cmdline.size() + 1, '\0');
    char* cmdline_cstr = &(cmdline[0]);
    ssize_t size = NormalizeCmdLine(&cmdline_cstr, cmdline.size());
    if (size == -1) {
      PERFETTO_PLOG("Failed to normalize cmdline %s. Stopping the parse.",
                    cmdlines[i].c_str());
      return base::nullopt;
    }
    normalized_cmdlines.emplace_back(cmdline_cstr, static_cast<size_t>(size));
  }
  return base::make_optional(normalized_cmdlines);
}

// This is mostly the same as GetHeapprofdProgramProperty in
// https://android.googlesource.com/platform/bionic/+/master/libc/bionic/malloc_common.cpp
// This should give the same result as GetHeapprofdProgramProperty.
bool GetCmdlineForPID(pid_t pid, std::string* name) {
  std::string filename = "/proc/" + std::to_string(pid) + "/cmdline";
  base::ScopedFile fd(base::OpenFile(filename, O_RDONLY | O_CLOEXEC));
  if (!fd) {
    PERFETTO_DPLOG("Failed to open %s", filename.c_str());
    return false;
  }
  char cmdline[512];
  const size_t max_read_size = sizeof(cmdline) - 1;
  ssize_t rd = read(*fd, cmdline, max_read_size);
  if (rd == -1) {
    PERFETTO_DPLOG("Failed to read %s", filename.c_str());
    return false;
  }

  if (rd == 0) {
    PERFETTO_DLOG("Empty cmdline for %" PRIdMAX ". Skipping.",
                  static_cast<intmax_t>(pid));
    return false;
  }

  // In some buggy kernels (before http://bit.ly/37R7qwL) /proc/pid/cmdline is
  // not NUL-terminated (see b/147438623). If we read < max_read_size bytes
  // assume we are hitting the aforementioned kernel bug and terminate anyways.
  const size_t rd_u = static_cast<size_t>(rd);
  if (rd_u >= max_read_size && memchr(cmdline, '\0', rd_u) == nullptr) {
    // We did not manage to read the first argument.
    PERFETTO_DLOG("Overflow reading cmdline for %" PRIdMAX,
                  static_cast<intmax_t>(pid));
    errno = EOVERFLOW;
    return false;
  }

  cmdline[rd] = '\0';
  char* cmdline_start = cmdline;
  ssize_t size = NormalizeCmdLine(&cmdline_start, rd_u);
  if (size == -1)
    return false;
  name->assign(cmdline_start, static_cast<size_t>(size));
  return true;
}

void FindAllProfilablePids(std::set<pid_t>* pids) {
  ForEachPid([pids](pid_t pid) {
    if (pid == getpid())
      return;

    char filename_buf[128];
    snprintf(filename_buf, sizeof(filename_buf), "/proc/%d/%s", pid, "cmdline");
    struct stat statbuf;
    // Check if we have permission to the process.
    if (stat(filename_buf, &statbuf) == 0)
      pids->emplace(pid);
  });
}

void FindPidsForCmdlines(const std::vector<std::string>& cmdlines,
                         std::set<pid_t>* pids) {
  ForEachPid([&cmdlines, pids](pid_t pid) {
    if (pid == getpid())
      return;
    std::string process_cmdline;
    process_cmdline.reserve(512);
    GetCmdlineForPID(pid, &process_cmdline);
    for (const std::string& cmdline : cmdlines) {
      if (process_cmdline == cmdline)
        pids->emplace(static_cast<pid_t>(pid));
    }
  });
}

base::Optional<std::string> ReadStatus(pid_t pid) {
  std::string path = "/proc/" + std::to_string(pid) + "/status";
  std::string status;
  bool read_proc = base::ReadFile(path, &status);
  if (!read_proc) {
    PERFETTO_ELOG("Failed to read %s", path.c_str());
    return base::nullopt;
  }
  return base::Optional<std::string>(status);
}

base::Optional<uint32_t> GetRssAnonAndSwap(const std::string& status) {
  auto anon_rss = ParseProcStatusSize(status, "RssAnon:");
  auto swap = ParseProcStatusSize(status, "VmSwap:");
  if (anon_rss.has_value() && swap.has_value()) {
    return *anon_rss + *swap;
  }
  return base::nullopt;
}

void RemoveUnderAnonThreshold(uint32_t min_size_kb, std::set<pid_t>* pids) {
  for (auto it = pids->begin(); it != pids->end();) {
    const pid_t pid = *it;

    base::Optional<std::string> status = ReadStatus(pid);
    base::Optional<uint32_t> rss_and_swap;
    if (status)
      rss_and_swap = GetRssAnonAndSwap(*status);

    if (rss_and_swap && rss_and_swap < min_size_kb) {
      PERFETTO_LOG("Removing pid %d from profiled set (anon: %d kB < %" PRIu32
                   ")",
                   pid, *rss_and_swap, min_size_kb);
      it = pids->erase(it);
    } else {
      ++it;
    }
  }
}

base::Optional<Uids> GetUids(const std::string& status) {
  auto entry_idx = status.find("Uid:");
  if (entry_idx == std::string::npos)
    return base::nullopt;

  Uids uids;
  const char* str = &status[entry_idx + 4];
  char* endptr;

  uids.real = strtoull(str, &endptr, 10);
  if (*endptr != ' ' && *endptr != '\t')
    return base::nullopt;

  str = endptr;
  uids.effective = strtoull(str, &endptr, 10);
  if (*endptr != ' ' && *endptr != '\t')
    return base::nullopt;

  str = endptr;
  uids.saved_set = strtoull(str, &endptr, 10);
  if (*endptr != ' ' && *endptr != '\t')
    return base::nullopt;

  str = endptr;
  uids.filesystem = strtoull(str, &endptr, 10);
  if (*endptr != '\n' && *endptr != '\0')
    return base::nullopt;
  return uids;
}

}  // namespace profiling
}  // namespace perfetto
