// Copyright 2018 The Fuchsia 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 "garnet/lib/process/process_builder.h"

#include <fcntl.h>
#include <lib/fdio/io.h>
#include <lib/fdio/limits.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/util.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/dlfcn.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>

#include <array>
#include <string_view>

#include "lib/svc/cpp/services.h"

namespace process {

namespace {

// This should match the values used by zircon/system/ulib/fdio/spawn.c
constexpr size_t kFdioResolvePrefixLen = 10;
const char kFdioResolvePrefix[kFdioResolvePrefixLen + 1] = "#!resolve ";

// It is possible to setup an infinite loop of resolvers. We want to avoid this
// being a common abuse vector, but also stay out of the way of any complex user
// setups. This value is the same as spawn.c's above.
constexpr int kFdioMaxResolveDepth = 256;

}  // namespace

ProcessBuilder::ProcessBuilder(std::shared_ptr<component::Services> services)
    : services_(services) {
  services_->ConnectToService(launcher_.NewRequest());
}

ProcessBuilder::ProcessBuilder(zx::job job,
                               std::shared_ptr<component::Services> services)
    : ProcessBuilder(services) {
  launch_info_.job = std::move(job);
}

ProcessBuilder::~ProcessBuilder() = default;

void ProcessBuilder::LoadVMO(zx::vmo executable) {
  launch_info_.executable = std::move(executable);
}

zx_status_t ProcessBuilder::LoadPath(const std::string& path) {
  int fd = open(path.c_str(), O_RDONLY);
  if (fd < 0)
    return ZX_ERR_IO;

  zx::vmo executable_vmo;
  zx_status_t status =
      fdio_get_vmo_clone(fd, executable_vmo.reset_and_get_address());
  close(fd);
  if (status != ZX_OK)
    return status;

  ::fidl::InterfaceHandle<::fuchsia::ldsvc::Loader> loader_iface;

  // Resolve VMOs containing #!resolve.
  fuchsia::process::ResolverSyncPtr resolver;  // Lazily bound.
  for (int i = 0; true; i++) {
    std::array<char, fuchsia::process::MAX_RESOLVE_NAME + kFdioResolvePrefixLen>
        head;
    head.fill(0);
    status = executable_vmo.read(head.data(), 0, head.size());
    if (status != ZX_OK)
      return status;
    if (memcmp(kFdioResolvePrefix, head.data(), kFdioResolvePrefixLen) != 0)
      break;  // No prefix match.

    if (i == kFdioMaxResolveDepth)
      return ZX_ERR_IO_INVALID;  // Too much nesting.

    // The process name is after the prefix until the first newline.
    std::string_view name(&head[kFdioResolvePrefixLen],
                          fuchsia::process::MAX_RESOLVE_NAME);
    if (auto newline_index = name.rfind('\n');
        newline_index != std::string_view::npos)
      name = name.substr(0, newline_index);

    // The resolver will give us a new VMO and loader to use.
    if (!resolver)
      services_->ConnectToService(resolver.NewRequest());
    resolver->Resolve(fidl::StringPtr(name.data(), name.size()), &status,
                      &executable_vmo, &loader_iface);
    if (status != ZX_OK)
      return status;
  }

  // Save the loader info.
  zx::handle loader = loader_iface.TakeChannel();
  if (!loader) {
    // Resolver didn't give us a specific one, clone ours.
    status = dl_clone_loader_service(loader.reset_and_get_address());
    if (status != ZX_OK)
      return status;
  }
  AddHandle(PA_LDSVC_LOADER, std::move(loader));

  // Save the VMO info. Name it with the file part of the path.
  launch_info_.executable = std::move(executable_vmo);
  const char* name = path.c_str();
  if (path.length() >= ZX_MAX_NAME_LEN) {
    size_t offset = path.rfind('/');
    if (offset != std::string::npos) {
      name += offset + 1;
    }
  }
  launch_info_.executable.set_property(ZX_PROP_NAME, name, strlen(name));

  return ZX_OK;
}

void ProcessBuilder::AddArgs(const std::vector<std::string>& argv) {
  if (argv.empty())
    return;
  if (launch_info_.name->empty())
    launch_info_.name.reset(argv[0]);
  fidl::VectorPtr<fidl::StringPtr> args;
  for (const auto& arg : argv)
    args.push_back(arg);
  launcher_->AddArgs(std::move(args));
}

void ProcessBuilder::AddHandle(uint32_t id, zx::handle handle) {
  handles_.push_back(fuchsia::process::HandleInfo{
      .id = id,
      .handle = std::move(handle),
  });
}

void ProcessBuilder::AddHandles(
    std::vector<fuchsia::process::HandleInfo> handles) {
  handles_->insert(handles_->end(), std::make_move_iterator(handles.begin()),
                   std::make_move_iterator(handles.end()));
}

void ProcessBuilder::SetDefaultJob(zx::job job) {
  handles_.push_back(fuchsia::process::HandleInfo{
      .id = PA_JOB_DEFAULT,
      .handle = std::move(job),
  });
}

void ProcessBuilder::SetName(std::string name) {
  launch_info_.name.reset(std::move(name));
}

void ProcessBuilder::CloneJob() {
  zx::job duplicate_job;
  if (launch_info_.job)
    launch_info_.job.duplicate(ZX_RIGHT_SAME_RIGHTS, &duplicate_job);
  else
    zx::job::default_job()->duplicate(ZX_RIGHT_SAME_RIGHTS, &duplicate_job);
  SetDefaultJob(std::move(duplicate_job));
}

void ProcessBuilder::CloneNamespace() {
  fdio_flat_namespace_t* flat = nullptr;
  zx_status_t status = fdio_ns_export_root(&flat);
  if (status == ZX_OK) {
    fidl::VectorPtr<fuchsia::process::NameInfo> names;
    for (size_t i = 0; i < flat->count; ++i) {
      names.push_back(fuchsia::process::NameInfo{
          flat->path[i],
          fidl::InterfaceHandle<fuchsia::io::Directory>(
              zx::channel(flat->handle[i])),
      });
    }
    launcher_->AddNames(std::move(names));
  }
  free(flat);
}

void ProcessBuilder::CloneStdio() {
  // These file descriptors might be closed. Skip over erros cloning them.
  CloneFileDescriptor(STDIN_FILENO, STDIN_FILENO);
  CloneFileDescriptor(STDOUT_FILENO, STDOUT_FILENO);
  CloneFileDescriptor(STDERR_FILENO, STDERR_FILENO);
}

void ProcessBuilder::CloneEnvironment() {
  auto env = fidl::VectorPtr<fidl::StringPtr>::New(0);
  for (size_t i = 0; environ[i]; ++i)
    env.push_back(environ[i]);
  launcher_->AddEnvirons(std::move(env));
}

void ProcessBuilder::CloneAll() {
  CloneJob();
  CloneNamespace();
  CloneStdio();
  CloneEnvironment();
}

zx_status_t ProcessBuilder::CloneFileDescriptor(int local_fd, int target_fd) {
  zx_handle_t fdio_handles[FDIO_MAX_HANDLES];
  uint32_t fdio_types[FDIO_MAX_HANDLES];
  zx_status_t status =
      fdio_clone_fd(local_fd, target_fd, fdio_handles, fdio_types);
  if (status < ZX_OK)
    return status;
  for (int i = 0; i < status; ++i) {
    handles_.push_back(fuchsia::process::HandleInfo{
        .id = fdio_types[i],
        .handle = zx::handle(fdio_handles[i]),
    });
  }
  return ZX_OK;
}

zx_status_t ProcessBuilder::Prepare(std::string* error_message) {
  zx_status_t status = ZX_OK;
  launcher_->AddHandles(std::move(handles_));
  if (!launch_info_.job) {
    status = zx::job::default_job()->duplicate(ZX_RIGHT_SAME_RIGHTS,
                                               &launch_info_.job);
    if (status != ZX_OK)
      return status;
  }
  fuchsia::process::CreateWithoutStartingResult result;
  status = launcher_->CreateWithoutStarting(std::move(launch_info_), &result);
  if (status != ZX_OK)
    return status;
  if (result.status != ZX_OK) {
    if (error_message)
      *error_message = result.error_message;
    return result.status;
  }
  if (!result.data)
    return ZX_ERR_INVALID_ARGS;
  data_ = std::move(*result.data);
  return ZX_OK;
}

zx_status_t ProcessBuilder::Start(zx::process* process_out) {
  zx_status_t status =
      zx_process_start(data_.process.get(), data_.thread.get(), data_.entry,
                       data_.sp, data_.bootstrap.release(), data_.vdso_base);
  if (status == ZX_OK && process_out)
    *process_out = std::move(data_.process);
  return status;
}

}  // namespace process
