// 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 "src/lib/process/process_builder.h"

#include <lib/component/incoming/cpp/protocol.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/io.h>
#include <lib/fdio/limits.h>
#include <lib/fdio/namespace.h>
#include <lib/fit/defer.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/status.h>
#include <zircon/syscalls.h>

#include <array>
#include <iterator>
#include <string_view>
#include <utility>

#include <fbl/unique_fd.h>

namespace process {

namespace {

// This should match the values used by sdk/lib/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(fidl::UnownedClientEnd<fuchsia_io::Directory> svc_dir)
    : svc_dir_(std::move(svc_dir)) {
  auto result = component::ConnectAt<fuchsia_process::Launcher>(svc_dir_);
  ZX_ASSERT_MSG(result.is_ok(), "%s", zx_status_get_string(result.error_value()));
  launcher_.Bind(std::move(*result));
}

ProcessBuilder::ProcessBuilder(zx::job job, fidl::UnownedClientEnd<fuchsia_io::Directory> svc_dir)
    : ProcessBuilder(std::move(svc_dir)) {
  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) {
  fbl::unique_fd fd;
  if (zx_status_t status =
          fdio_open_fd(path.c_str(),
                       static_cast<uint32_t>(fuchsia_io::OpenFlags::kRightReadable |
                                             fuchsia_io::OpenFlags::kRightExecutable),
                       fd.reset_and_get_address());
      status != ZX_OK) {
    return status;
  }

  zx::vmo executable_vmo;
  if (zx_status_t status = fdio_get_vmo_exec(fd.get(), executable_vmo.reset_and_get_address());
      status != ZX_OK) {
    return status;
  }

  fidl::ClientEnd<fuchsia_ldsvc::Loader> loader_iface;

  // Resolve VMOs containing #!resolve.
  fidl::SyncClient<fuchsia_process::Resolver> resolver;  // Lazily bound.
  for (int i = 0; true; i++) {
    std::array<char, fuchsia_process::kMaxResolveNameSize + kFdioResolvePrefixLen> head;
    head.fill(0);
    if (zx_status_t status = executable_vmo.read(head.data(), 0, head.size()); 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::kMaxResolveNameSize);
    if (size_t 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) {
      if (auto res = component::ConnectAt<fuchsia_process::Resolver>(svc_dir_); res.is_ok()) {
        resolver.Bind(std::move(*res));
      } else {
        return res.error_value();
      }
    }
    if (auto res = resolver->Resolve(std::string(name.data(), name.size())); res.is_ok()) {
      if (res->status() != ZX_OK) {
        return res->status();
      }
      executable_vmo = std::move(res->executable());
      loader_iface = std::move(res->ldsvc());
    } else {
      return res.error_value().status();
    }
  }

  // Save the loader info.
  zx::handle loader = loader_iface.TakeChannel();
  if (!loader) {
    // Resolver didn't give us a specific one, clone ours.
    if (zx_status_t status = dl_clone_loader_service(loader.reset_and_get_address());
        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;
    }
  }
  return launch_info_.executable().set_property(ZX_PROP_NAME, name, strlen(name));
}

zx_status_t ProcessBuilder::AddArgs(const std::vector<std::string>& argv) {
  if (argv.empty()) {
    return ZX_OK;
  }
  if (launch_info_.name().empty()) {
    launch_info_.name() = argv[0];
  }
  std::vector<std::vector<uint8_t>> args;
  args.reserve(argv.size());
  for (const auto& arg : argv) {
    args.emplace_back(arg.begin(), arg.end());
  }
  if (auto res = launcher_->AddArgs(std::move(args)); res.is_error()) {
    return res.error_value().status();
  }
  return ZX_OK;
}

void ProcessBuilder::AddHandle(uint32_t id, zx::handle handle) {
  handles_.emplace_back(std::move(handle), id);
}

void ProcessBuilder::AddHandles(std::vector<fuchsia_process::HandleInfo> handles) {
  std::copy(std::make_move_iterator(handles.begin()), std::make_move_iterator(handles.end()),
            std::back_inserter(handles_));
}

void ProcessBuilder::SetDefaultJob(zx::job job) {
  handles_.emplace_back(std::move(job), PA_JOB_DEFAULT);
}

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

zx_status_t ProcessBuilder::CloneJob() {
  zx::job duplicate_job;
  if (launch_info_.job()) {
    if (zx_status_t status = launch_info_.job().duplicate(ZX_RIGHT_SAME_RIGHTS, &duplicate_job);
        status != ZX_OK) {
      return status;
    }
  } else {
    if (zx_status_t status =
            zx::job::default_job()->duplicate(ZX_RIGHT_SAME_RIGHTS, &duplicate_job);
        status != ZX_OK) {
      return status;
    }
  }
  SetDefaultJob(std::move(duplicate_job));
  return ZX_OK;
}

zx_status_t ProcessBuilder::CloneNamespace() {
  fdio_flat_namespace_t* flat = nullptr;
  if (zx_status_t status = fdio_ns_export_root(&flat); status != ZX_OK) {
    return status;
  }
  auto cleanup = fit::defer([flat]() { fdio_ns_free_flat_ns(flat); });
  std::vector<fuchsia_process::NameInfo> names;
  for (size_t i = 0; i < flat->count; ++i) {
    names.emplace_back(flat->path[i],
                       fidl::ClientEnd<fuchsia_io::Directory>(zx::channel(flat->handle[i])));
  }
  if (auto res = launcher_->AddNames(std::move(names)); res.is_error()) {
    return res.error_value().status();
  }
  return ZX_OK;
}

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

zx_status_t ProcessBuilder::CloneEnvironment() {
  std::vector<std::vector<uint8_t>> env;
  for (size_t i = 0; environ[i]; ++i) {
    std::string_view var{environ[i]};
    env.emplace_back(var.begin(), var.end());
  }
  if (auto res = launcher_->AddEnvirons(std::move(env)); res.is_error()) {
    return res.error_value().status();
  }
  return ZX_OK;
}

zx_status_t ProcessBuilder::CloneAll() {
  if (zx_status_t status = CloneJob(); status != ZX_OK) {
    return status;
  }
  if (zx_status_t status = CloneNamespace(); status != ZX_OK) {
    return status;
  }
  if (zx_status_t status = CloneEnvironment(); status != ZX_OK) {
    return status;
  }
  CloneStdio();
  return ZX_OK;
}

zx_status_t ProcessBuilder::CloneFileDescriptor(int local_fd, int target_fd) {
  zx::handle fd_handle;
  if (zx_status_t status = fdio_fd_clone(local_fd, fd_handle.reset_and_get_address());
      status != ZX_OK) {
    return status;
  }
  handles_.emplace_back(std::move(fd_handle), PA_HND(PA_FD, target_fd));
  return ZX_OK;
}

zx_status_t ProcessBuilder::Prepare(std::string* error_message) {
  if (auto res = launcher_->AddHandles(std::move(handles_)); res.is_error()) {
    return res.error_value().status();
  }
  if (!launch_info_.job()) {
    if (zx_status_t status =
            zx::job::default_job()->duplicate(ZX_RIGHT_SAME_RIGHTS, &launch_info_.job());
        status != ZX_OK) {
      return status;
    }
  }
  auto res = launcher_->CreateWithoutStarting(std::move(launch_info_));
  if (res.is_error()) {
    return res.error_value().status();
  }
  if (res->status() != ZX_OK) {
    return res->status();
  }
  if (!res->data()) {
    return ZX_ERR_INVALID_ARGS;
  }
  data_ = std::move(*res->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_.stack(),
                       data_.bootstrap().release(), data_.vdso_base());
  if (status == ZX_OK && process_out)
    *process_out = std::move(data_.process());
  return status;
}

}  // namespace process
