/*
 * 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/memory/proc_utils.h"

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

#include "perfetto/ext/base/file_utils.h"

namespace perfetto {
namespace profiling {
namespace {

#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)

const char* FindChar(const char* s, char c, size_t n) {
  std::string str(s, n);
  auto idx = str.rfind(c);
  if (idx == std::string::npos)
    return nullptr;
  return s + n;
}

void* memrchr(const void* s, int c, size_t n) {
  return static_cast<void*>(const_cast<char*>(
      FindChar(static_cast<const char*>(s), static_cast<char>(c), n)));
}

#endif

bool GetProcFile(pid_t pid, const char* file, char* filename_buf, size_t size) {
  ssize_t written = snprintf(filename_buf, size, "/proc/%d/%s", pid, file);
  if (written < 0 || static_cast<size_t>(written) >= size) {
    if (written < 0)
      PERFETTO_ELOG("Failed to concatenate cmdline file.");
    else
      PERFETTO_ELOG("Overflow when concatenating cmdline file.");
    return false;
  }
  return true;
}

}  // namespace

bool NormalizeCmdLine(char* cmdline, size_t size, std::string* name) {
  char* first_arg = static_cast<char*>(memchr(cmdline, '\0', size));
  if (first_arg == nullptr) {
    PERFETTO_DLOG("Overflow reading cmdline");
    errno = EOVERFLOW;
    return false;
  }
  // For consistency with what we do with Java app cmdlines, trim everything
  // after the @ sign of the first arg.
  char* first_at = static_cast<char*>(memchr(cmdline, '@', size));
  if (first_at != nullptr && first_at < first_arg) {
    *first_at = '\0';
    first_arg = first_at;
  }
  char* start = static_cast<char*>(
      memrchr(cmdline, '/', static_cast<size_t>(first_arg - cmdline)));
  if (start == first_arg) {
    // The first argument ended in a slash.
    PERFETTO_DLOG("cmdline ends in /");
    errno = EINVAL;
    return false;
  } else if (start == nullptr) {
    start = cmdline;
  } else {
    // Skip the /.
    start++;
  }
  size_t name_size = static_cast<size_t>(first_arg - start);
  name->assign(start, name_size);
  return true;
}

std::vector<std::string> NormalizeCmdlines(
    const std::vector<std::string>& cmdlines) {
  std::vector<std::string> normalized_cmdlines;
  for (std::string cmdline : cmdlines) {
    // Add nullbyte to make sure it's a C string.
    cmdline.resize(cmdline.size() + 1, '\0');
    std::string normalized;
    if (!NormalizeCmdLine(&(cmdline[0]), cmdline.size(), &normalized)) {
      PERFETTO_ELOG("Failed to normalize cmdline %s. Skipping.",
                    cmdline.c_str());
      continue;
    }
    normalized_cmdlines.emplace_back(std::move(normalized));
  }
  return 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_DLOG("Failed to open %s", filename.c_str());
    return false;
  }
  char cmdline[512];
  ssize_t rd = read(*fd, cmdline, sizeof(cmdline) - 1);
  if (rd == -1) {
    PERFETTO_DLOG("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;
  }

  // We did not manage to read the first argument.
  if (memchr(cmdline, '\0', static_cast<size_t>(rd)) == nullptr) {
    PERFETTO_DLOG("Overflow reading cmdline for %" PRIdMAX,
                  static_cast<intmax_t>(pid));
    errno = EOVERFLOW;
    return false;
  }

  cmdline[rd] = '\0';
  return NormalizeCmdLine(cmdline, static_cast<size_t>(rd), name);
}

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

    char filename_buf[128];
    if (!GetProcFile(pid, "cmdline", filename_buf, sizeof(filename_buf)))
      return;
    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));
    }
  });
}

}  // namespace profiling
}  // namespace perfetto
