// 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 <fcntl.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fidl/fuchsia.process/cpp/wire.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/io.h>
#include <lib/fdio/limits.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/spawn.h>
#include <lib/fidl/txn_header.h>
#include <lib/fit/defer.h>
#include <lib/zx/channel.h>
#include <lib/zx/time.h>
#include <lib/zx/vmo.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/dlfcn.h>
#include <zircon/errors.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/utc.h>

#include <algorithm>
#include <bitset>
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <iterator>
#include <list>
#include <string>
#include <utility>
#include <vector>

#include <fbl/unique_fd.h>

#include "internal.h"

namespace fio = fuchsia_io;
namespace fprocess = fuchsia_process;

#define FDIO_RESOLVE_PREFIX "#!resolve "
#define FDIO_RESOLVE_PREFIX_LEN 10

// It is possible to setup an infinite loop of interpreters. We want to avoid this being a common
// abuse vector, but also stay out of the way of any complex user setups.
#define FDIO_SPAWN_MAX_INTERPRETER_DEPTH 255

// Maximum allowed length of a #! shebang directive.
// This applies to both types of #! directives - both the '#!resolve' special case and the general
// '#!' case with an arbitrary interpreter - but we use the fuchsia.process/Resolver limit rather
// than define a separate arbitrary limit.
#define FDIO_SPAWN_MAX_INTERPRETER_LINE_LEN \
  (fprocess::wire::kMaxResolveNameSize + FDIO_RESOLVE_PREFIX_LEN)
static_assert(FDIO_SPAWN_MAX_INTERPRETER_LINE_LEN < ZX_MIN_PAGE_SIZE,
              "max #! interpreter line length must be less than smallest page size");

#define FDIO_SPAWN_LAUNCH_HANDLE_EXECUTABLE ((size_t)0u)
#define FDIO_SPAWN_LAUNCH_HANDLE_JOB ((size_t)1u)
#define FDIO_SPAWN_LAUNCH_HANDLE_COUNT ((size_t)2u)

#define FDIO_SPAWN_LAUNCH_REPLY_HANDLE_COUNT ((size_t)1u)

// The fdio_spawn_action_t is replicated in various ffi interfaces, including
// the rust and golang standard libraries.
static_assert(sizeof(fdio_spawn_action_t) == 24, "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, action) == 0,
              "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, fd) == 8, "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, fd.local_fd) == 8,
              "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, fd.target_fd) == 12,
              "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, ns) == 8, "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, ns.prefix) == 8,
              "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, ns.handle) == 16,
              "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, h) == 8, "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, h.id) == 8,
              "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, h.handle) == 12,
              "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, name) == 8,
              "fdio_spawn_action_t must have a stable ABI");
static_assert(offsetof(fdio_spawn_action_t, name.data) == 8,
              "fdio_spawn_action_t must have a stable ABI");

namespace {

void report_error(char* err_msg, const char* format, ...) {
  if (!err_msg)
    return;
  va_list args;
  va_start(args, format);
  vsnprintf(err_msg, FDIO_SPAWN_ERR_MSG_MAX_LENGTH, format, args);
  va_end(args);
}

zx_status_t load_path(const char* path, zx::vmo* out_vmo, char* err_msg) {
  fbl::unique_fd fd;
  zx_status_t status = fdio_open_fd(path,
                                    static_cast<uint32_t>(fio::wire::OpenFlags::kRightReadable |
                                                          fio::wire::OpenFlags::kRightExecutable),
                                    fd.reset_and_get_address());
  if (status != ZX_OK) {
    report_error(err_msg, "Could not open file");
    return status;
  }

  zx::vmo vmo;
  status = fdio_get_vmo_exec(fd.get(), vmo.reset_and_get_address());
  if (status != ZX_OK) {
    report_error(err_msg, "Could not clone VMO for file");
    return status;
  }

  if (strlen(path) >= ZX_MAX_NAME_LEN) {
    const char* p = strrchr(path, '/');
    if (p != nullptr) {
      path = p + 1;
    }
  }

  status = vmo.set_property(ZX_PROP_NAME, path, strlen(path));
  if (status != ZX_OK) {
    report_error(err_msg, "Could not associate pathname with VMO");
    return status;
  }

  *out_vmo = std::move(vmo);
  return status;
}

// resolve_name makes a call to the fuchsia.process.Resolver service and may return a vmo and
// associated loader service, if the name resolves within the current realm.
zx_status_t resolve_name(const char* name, size_t name_len, zx::vmo* out_executable,
                         zx::channel* out_ldsvc, char* err_msg) {
  zx::status endpoints = fidl::CreateEndpoints<fprocess::Resolver>();
  if (!endpoints.is_ok()) {
    report_error(err_msg, "failed to create channel for resolver service: %d",
                 endpoints.status_value());
    return ZX_ERR_INTERNAL;
  }

  fidl::WireSyncClient resolver{std::move(endpoints->client)};
  zx_status_t status =
      fdio_service_connect_by_name(fidl::DiscoverableProtocolName<fprocess::Resolver>,
                                   endpoints->server.TakeChannel().release());
  if (status != ZX_OK) {
    report_error(err_msg, "failed to connect to resolver service: %d (%s)", status,
                 zx_status_get_string(status));
    return ZX_ERR_INTERNAL;
  }

  auto response = resolver->Resolve(fidl::StringView::FromExternal(name, name_len));

  status = response.status();
  if (status != ZX_OK) {
    report_error(err_msg, "failed to send resolver request: %d (%s)", status,
                 zx_status_get_string(status));
    return ZX_ERR_INTERNAL;
  }

  status = response->status;
  if (status != ZX_OK) {
    report_error(err_msg, "failed to resolve %.*s: %d (%s)", name_len, name, status,
                 zx_status_get_string(status));
    return status;
  }

  *out_executable = std::move(response->executable);
  *out_ldsvc = std::move(response->ldsvc.channel());

  return ZX_OK;
}

// Find the starting point of the interpreter and the interpreter arguments in a #! script header.
// Note that the input buffer (line) will be modified to add a NUL after the interpreter name.
zx_status_t parse_interp_spec(char* line, char** interp_start, char** args_start) {
  *args_start = nullptr;

  // Skip the '#!' prefix
  char* next_char = line + 2;

  // Skip whitespace
  next_char += strspn(next_char, " \t");

  // No interpreter specified
  if (*next_char == '\0')
    return ZX_ERR_INVALID_ARGS;

  *interp_start = next_char;

  // Skip the interpreter name
  next_char += strcspn(next_char, " \t");

  if (*next_char == '\0')
    return ZX_OK;

  // Add a NUL after the interpreter name
  *next_char++ = '\0';

  // Look for the args
  next_char += strspn(next_char, " \t");

  if (*next_char == '\0')
    return ZX_OK;

  *args_start = next_char;
  return ZX_OK;
}

// handle_interpreters checks whether the provided vmo starts with a '#!' directive, and handles
// appropriately if it does.
//
// If a '#!' directive is present, we check whether it is either:
//   1) a specific '#!resolve' directive, in which case resolve_name is used to resolve the given
//      executable name into a new executable vmo and appropriate loader service through the
//      fuchsia.process.Resolver service, or
//   2) a general '#!' shebang interpreter directive, in which case the given interpreter is loaded
//      via the current loader service and executable is updated. extra_args will also be appended
//      to, and these arguments should be added to the front of argv.
//
// Directives will be resolved until none are detected, an error is encountered, or a resolution
// limit is reached. Also, mixing the two types is unsupported.
//
// The executable and ldsvc paramters are both inputs to and outputs from this function, and are
// updated based on the resolved directives. executable must always be valid, and ldsvc must be
// valid at minimum for the 2nd case above, though it should generally always be valid as well when
// calling this.
zx_status_t handle_interpreters(zx::vmo* executable, zx::channel* ldsvc,
                                std::list<std::string>* extra_args, char* err_msg) {
  extra_args->clear();

  // Mixing #!resolve and general #! within a single spawn is unsupported so that the #!
  // interpreters can simply be loaded from the current namespace.
  bool handled_resolve = false;
  bool handled_shebang = false;
  for (size_t depth = 0; true; ++depth) {
    // VMO sizes are page aligned and MAX_INTERPRETER_LINE_LEN < ZX_MIN_PAGE_SIZE (asserted above),
    // so there's no use in checking VMO size explicitly here. Either the read fails because the VMO
    // is zero-sized, and we handle it, or sizeof(line) < vmo_size.
    char line[FDIO_SPAWN_MAX_INTERPRETER_LINE_LEN];
    memset(line, 0, sizeof(line));
    zx_status_t status = executable->read(line, 0, sizeof(line));
    if (status != ZX_OK) {
      report_error(err_msg, "error reading executable vmo: %d (%s)", status,
                   zx_status_get_string(status));
      return status;
    }

    // If no "#!" prefix is present, we're done; treat this as an ELF file and continue loading.
    if (line[0] != '#' || line[1] != '!') {
      break;
    }

    // Interpreter resolution is not allowed to carry on forever.
    if (depth == FDIO_SPAWN_MAX_INTERPRETER_DEPTH) {
      report_error(err_msg, "hit recursion limit resolving interpreters");
      return ZX_ERR_IO_INVALID;
    }

    // Find the end of the first line and NUL-terminate it to aid in parsing.
    char* line_end = reinterpret_cast<char*>(memchr(line, '\n', sizeof(line)));
    if (line_end) {
      *line_end = '\0';
    } else {
      // If there's no newline, then the script may be a single line and lack a trailing newline.
      // Look for the actual end of the script.
      line_end = reinterpret_cast<char*>(memchr(line, '\0', sizeof(line)));
      if (line_end == nullptr) {
        // This implies that the first line is longer than MAX_INTERPRETER_LINE_LEN.
        report_error(err_msg, "first line of script is too long");
        return ZX_ERR_OUT_OF_RANGE;
      }
    }
    size_t line_len = line_end - line;

    if (memcmp(FDIO_RESOLVE_PREFIX, line, FDIO_RESOLVE_PREFIX_LEN) == 0) {
      // This is a "#!resolve" directive; use fuchsia.process.Resolve to resolve the name into a new
      // executable and appropriate loader.
      handled_resolve = true;
      if (handled_shebang) {
        report_error(err_msg, "already resolved a #! directive, mixing #!resolve is unsupported");
        return ZX_ERR_NOT_SUPPORTED;
      }

      char* name = &line[FDIO_RESOLVE_PREFIX_LEN];
      size_t name_len = line_len - FDIO_RESOLVE_PREFIX_LEN;
      status = resolve_name(name, name_len, executable, ldsvc, err_msg);
      if (status != ZX_OK) {
        return status;
      }
    } else {
      // This is a general "#!" interpreter directive.
      handled_shebang = true;
      if (handled_resolve) {
        report_error(err_msg, "already resolved a #!resolve directive, mixing #! is unsupported");
        return ZX_ERR_NOT_SUPPORTED;
      }

      // Parse the interpreter spec to find the interpreter name and any args, and add those to
      // extra_args.
      char* interp_start;
      char* args_start;
      status = parse_interp_spec(line, &interp_start, &args_start);
      if (status != ZX_OK) {
        report_error(err_msg, "invalid #! interpreter spec");
        return status;
      }

      // args_start and interp_start are safe to treat as NUL terminated because parse_interp_spec
      // adds a NUL at the end of the interpreter name and we added an overall line NUL terminator
      // above when finding the line end.
      if (args_start != nullptr) {
        extra_args->emplace_front(args_start);
      }
      extra_args->emplace_front(interp_start);

      // Load the specified interpreter from the current namespace.
      char path_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
      status = load_path(interp_start, executable, path_msg);
      if (status != ZX_OK) {
        report_error(err_msg, "failed to load script interpreter '%s': %s", interp_start, path_msg);
        return status;
      }
    }
  }
  return ZX_OK;
}

// |SpawnActions| is a C++ helper that owns the resources referenced by a list
// of |fdio_spawn_action_t|, and offers range-based iteration.
class SpawnActions {
 public:
  SpawnActions(const fdio_spawn_action_t* actions, size_t action_count)
      : actions_(actions), action_count_(action_count) {}

  ~SpawnActions() {
    // |actions_| will be nullptr if the user did not supply any actions, or if
    // the actions ownership have been moved to a |ConsumingIterator|.
    if (!actions_)
      return;

    for (size_t i = 0; i < action_count_; ++i) {
      Free(actions_[i]);
    }
  }

  // Iterates through the list of actions without consuming them.
  const fdio_spawn_action_t* begin() const { return actions_; }
  const fdio_spawn_action_t* end() const { return &actions_[action_count_]; }

  // An iterator-style object that only allows traversing through the list of
  // spawn actions once. The contract is that the user consumes any resources
  // held by a particular action as they iterate over it.
  //
  // If the user did not finish iterating over all the actions, the iterator
  // will close any resources held in the remaining actions.
  class ConsumingIterator {
   public:
    ConsumingIterator(const fdio_spawn_action_t* actions, size_t action_count)
        : actions_(actions), action_count_(action_count), used_(0) {}

    ~ConsumingIterator() {
      // |actions_| will be nullptr if the user did not supply any actions.
      if (!actions_)
        return;

      for (size_t i = used_; i < action_count_; ++i) {
        Free(actions_[i]);
      }
    }

    ConsumingIterator(const ConsumingIterator&) = delete;
    ConsumingIterator& operator=(ConsumingIterator&) = delete;
    ConsumingIterator(ConsumingIterator&&) = delete;
    ConsumingIterator& operator=(ConsumingIterator&&) = delete;

    bool has_next() const { return used_ < action_count_; }
    size_t index() const { return used_; }
    const fdio_spawn_action_t& operator*() const { return actions_[used_]; }
    const fdio_spawn_action_t* operator->() { return &actions_[used_]; }
    ConsumingIterator& operator++() {
      used_++;
      return *this;
    }

   private:
    const fdio_spawn_action_t* actions_;
    size_t action_count_;
    size_t used_;
  };

  // Converts the object into a consuming iterator. This transfers the resources
  // owned by |SpawnActions| into the iterator.
  ConsumingIterator ConsumeWhileIterating() && {
    auto* actions = actions_;
    actions_ = nullptr;
    if (action_count_ > 0) {
      ZX_DEBUG_ASSERT(actions != nullptr);
    }
    return ConsumingIterator(actions, action_count_);
  }

  // Frees the resources held in an |action|. If new spawn action types are
  // introduced that holds resources, corresponding cleanup logic should be
  // added here.
  static void Free(const fdio_spawn_action_t& action) {
    switch (action.action) {
      case FDIO_SPAWN_ACTION_ADD_NS_ENTRY:
        zx_handle_close(action.ns.handle);
        break;
      case FDIO_SPAWN_ACTION_ADD_HANDLE:
        zx_handle_close(action.h.handle);
        break;
      case FDIO_SPAWN_ACTION_TRANSFER_FD:
        close(action.fd.local_fd);
        break;
      default:
        break;
    }
  }

 private:
  const fdio_spawn_action_t* actions_;
  size_t action_count_;
};

// Bounds-checking helper for populating an array of |T| of predefined capacity.
template <typename T>
class Inserter {
 public:
  Inserter(T* data, size_t capacity) : data_(data), used_(0), capacity_(capacity) {}

  T* AddNext() {
    ZX_DEBUG_ASSERT(used_ < capacity_);
    size_t idx = used_;
    used_++;
    return &data_[idx];
  }

  auto vector_view() { return fidl::VectorView<T>::FromExternal(data_, used_); }

  size_t used() const { return used_; }

 private:
  T* data_;
  size_t used_;
  size_t capacity_;
};

zx_status_t send_handles_and_namespace(const fidl::WireSyncClient<fprocess::Launcher>& launcher,
                                       size_t handle_capacity, uint32_t flags, zx_handle_t job,
                                       zx::channel ldsvc, zx_handle_t utc_clock, size_t name_count,
                                       fdio_flat_namespace_t* flat,
                                       SpawnActions::ConsumingIterator action, char* err_msg) {
  zx_status_t status = ZX_OK;
  // TODO(abarth): In principle, we should chunk array into separate
  // messages if we exceed ZX_CHANNEL_MAX_MSG_HANDLES.

  // VLAs cannot have zero size.
  fprocess::wire::HandleInfo handle_infos_storage[std::max(handle_capacity, 1UL)];
  fprocess::wire::NameInfo names_storage[std::max(name_count, 1UL)];
  // VLAs cannot be initialized.
  memset(handle_infos_storage, 0, sizeof(handle_infos_storage));
  memset(names_storage, 0, sizeof(names_storage));
  Inserter handle_infos(handle_infos_storage, handle_capacity);
  Inserter names(names_storage, name_count);

  std::bitset<FDIO_MAX_FD> fds_in_use;
  auto check_fd = [&fds_in_use](int fd) -> zx_status_t {
    fd &= ~FDIO_FLAG_USE_FOR_STDIO;
    if (fd < 0 || fd >= FDIO_MAX_FD) {
      return ZX_ERR_OUT_OF_RANGE;
    }
    if (fds_in_use.test(fd)) {
      return ZX_ERR_ALREADY_EXISTS;
    }
    fds_in_use.set(fd);
    return ZX_OK;
  };

  if ((flags & FDIO_SPAWN_CLONE_JOB) != 0) {
    auto* handle_info = handle_infos.AddNext();
    handle_info->id = PA_JOB_DEFAULT;
    status =
        zx_handle_duplicate(job, ZX_RIGHT_SAME_RIGHTS, handle_info->handle.reset_and_get_address());
    if (status != ZX_OK) {
      report_error(err_msg, "failed to duplicate job: %d (%s)", status,
                   zx_status_get_string(status));
      return status;
    }
  }

  // ldsvc may be valid if flags contains FDIO_SPAWN_DEFAULT_LDSVC or if a ldsvc was obtained
  // through handling a '#!resolve' directive.
  if (ldsvc.is_valid()) {
    auto* handle_info = handle_infos.AddNext();
    handle_info->id = PA_LDSVC_LOADER;
    handle_info->handle = std::move(ldsvc);
  }

  for (; action.has_next(); ++action) {
    switch (action->action) {
      case FDIO_SPAWN_ACTION_CLONE_FD: {
        zx_handle_t fd_handle = ZX_HANDLE_INVALID;
        status = check_fd(action->fd.target_fd);
        if (status != ZX_OK) {
          report_error(err_msg, "invalid target %d to clone fd %d (action index %zu): %d",
                       action->fd.target_fd, action->fd.local_fd, action.index(), status);
          return status;
        }
        status = fdio_fd_clone(action->fd.local_fd, &fd_handle);
        if (status != ZX_OK) {
          report_error(err_msg, "failed to clone fd %d (action index %zu): %d", action->fd.local_fd,
                       action.index(), status);
          return status;
        }
        auto* handle_info = handle_infos.AddNext();
        handle_info->id = PA_HND(PA_FD, action->fd.target_fd);
        handle_info->handle.reset(fd_handle);
        break;
      }
      case FDIO_SPAWN_ACTION_TRANSFER_FD: {
        zx_handle_t fd_handle = ZX_HANDLE_INVALID;
        status = check_fd(action->fd.target_fd);
        if (status != ZX_OK) {
          report_error(err_msg, "invalid target %d to transfer fd %d (action index %zu): %d",
                       action->fd.target_fd, action->fd.local_fd, action.index(), status);
          return status;
        }
        status = fdio_fd_transfer(action->fd.local_fd, &fd_handle);
        if (status != ZX_OK) {
          report_error(err_msg, "failed to transfer fd %d (action index %zu): %d",
                       action->fd.local_fd, action.index(), status);
          return status;
        }
        auto* handle_info = handle_infos.AddNext();
        handle_info->id = PA_HND(PA_FD, action->fd.target_fd);
        handle_info->handle.reset(fd_handle);
        break;
      }
      case FDIO_SPAWN_ACTION_ADD_NS_ENTRY: {
        auto* name = names.AddNext();
        auto path = action->ns.prefix;
        name->path = fidl::StringView::FromExternal(path);
        name->directory = fidl::ClientEnd<fio::Directory>(zx::channel(action->ns.handle));
        break;
      }
      case FDIO_SPAWN_ACTION_ADD_HANDLE: {
        if (PA_HND_TYPE(action->h.id) == PA_FD) {
          int fd = PA_HND_ARG(action->h.id) & ~FDIO_FLAG_USE_FOR_STDIO;
          status = check_fd(fd);
          if (status != ZX_OK) {
            report_error(err_msg, "add-handle action has invalid fd %d (action index %zu): %d", fd,
                         action.index(), status);
            return status;
          }
        }
        auto* handle_info = handle_infos.AddNext();
        handle_info->id = action->h.id;
        handle_info->handle.reset(action->h.handle);
        break;
      }
      default: {
        break;
      }
    }
  }

  // Do these after generic actions so that actions can set these fds first.
  if ((flags & FDIO_SPAWN_CLONE_STDIO) != 0) {
    for (int fd = 0; fd < 3; ++fd) {
      if (fds_in_use.test(fd)) {
        // Skip a standard fd that was explicitly set by an action.
        continue;
      }
      zx_handle_t fd_handle = ZX_HANDLE_INVALID;
      status = fdio_fd_clone(fd, &fd_handle);
      if (status == ZX_ERR_INVALID_ARGS || status == ZX_ERR_NOT_SUPPORTED) {
        // This file descriptor is either closed, or something that doesn't
        // support cloning into a handle (e.g. a null fdio object).
        // We just skip it rather than generating an error.
        continue;
      }
      if (status != ZX_OK) {
        report_error(err_msg, "failed to clone fd %d: %d (%s)", fd, status,
                     zx_status_get_string(status));
        return status;
      }
      auto* handle_info = handle_infos.AddNext();
      handle_info->id = PA_HND(PA_FD, fd);
      handle_info->handle.reset(fd_handle);
    }
  }

  if ((flags & FDIO_SPAWN_CLONE_UTC_CLOCK) != 0) {
    if (utc_clock != ZX_HANDLE_INVALID) {
      auto* handle_info = handle_infos.AddNext();
      handle_info->id = PA_CLOCK_UTC;
      status = zx_handle_duplicate(
          utc_clock, ZX_RIGHT_READ | ZX_RIGHT_WAIT | ZX_RIGHT_DUPLICATE | ZX_RIGHT_TRANSFER,
          handle_info->handle.reset_and_get_address());
      if (status != ZX_OK) {
        report_error(err_msg, "failed to clone UTC clock: %d (%s)", status,
                     zx_status_get_string(status));
        return status;
      }
    }
  }

  ZX_DEBUG_ASSERT(handle_infos.used() <= handle_capacity);
  status = launcher->AddHandles(handle_infos.vector_view()).status();
  if (status != ZX_OK) {
    report_error(err_msg, "failed to send handles: %d (%s)", status, zx_status_get_string(status));
    return status;
  }

  if (flat) {
    for (size_t i = 0; i < flat->count; i++) {
      auto* name = names.AddNext();
      auto path = flat->path[i];
      name->path = fidl::StringView::FromExternal(path);
      name->directory = fidl::ClientEnd<fio::Directory>(zx::channel(flat->handle[i]));
      flat->handle[i] = ZX_HANDLE_INVALID;
    }
  }

  ZX_DEBUG_ASSERT(names.used() == name_count);
  status = launcher->AddNames(names.vector_view()).status();
  if (status != ZX_OK) {
    report_error(err_msg, "failed send namespace: %d (%s)", status, zx_status_get_string(status));
    return status;
  }

  return ZX_OK;
}

}  // namespace

__EXPORT
zx_status_t fdio_spawn(zx_handle_t job, uint32_t flags, const char* path, const char* const* argv,
                       zx_handle_t* process_out) {
  return fdio_spawn_etc(job, flags, path, argv, nullptr, 0, nullptr, process_out, nullptr);
}

__EXPORT
zx_status_t fdio_spawn_etc(zx_handle_t job, uint32_t flags, const char* path,
                           const char* const* argv, const char* const* explicit_environ,
                           size_t action_count, const fdio_spawn_action_t* actions,
                           zx_handle_t* process_out, char* err_msg) {
  zx::vmo executable;

  char path_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
  zx_status_t status = load_path(path, &executable, path_msg);

  if (status != ZX_OK) {
    report_error(err_msg, "failed to load executable from %s: %s", path, path_msg);
    // Set |err_msg| to nullptr to prevent |fdio_spawn_vmo| from generating
    // a less useful error message.
    err_msg = nullptr;
  }

  // Always call fdio_spawn_vmo to clean up arguments. If |executable| is
  // |ZX_HANDLE_INVALID|, then |fdio_spawn_vmo| will generate an error.
  zx_status_t spawn_status =
      fdio_spawn_vmo(job, flags, executable.release(), argv, explicit_environ, action_count,
                     actions, process_out, err_msg);

  // Use |status| if we already had an error before calling |fdio_spawn_vmo|.
  // Otherwise, we'll always return |ZX_ERR_INVALID_ARGS| rather than the more
  // useful status from |load_path|.
  return status != ZX_OK ? status : spawn_status;
}

namespace {

bool should_clone_namespace(std::string_view path, const std::vector<std::string_view>& prefixes) {
  for (const auto& prefix : prefixes) {
    // Only share path if there is a directory prefix in |prefixes| that matches the path.
    // Also take care to not match partial directory names. Ex, /foo should not match
    // /foobar.
    if (path.compare(0, prefix.size(), prefix) == 0 &&
        (path.size() == prefix.size() || path[prefix.size()] == '/')) {
      return true;
    }
  }
  return false;
}

void filter_flat_namespace(fdio_flat_namespace_t* flat,
                           const std::vector<std::string_view>& prefixes) {
  size_t read, write;
  for (read = 0, write = 0; read < flat->count; ++read) {
    if (should_clone_namespace(flat->path[read], prefixes)) {
      if (read != write) {
        flat->handle[write] = flat->handle[read];
        flat->type[write] = flat->type[read];
        const_cast<const char**>(flat->path)[write] = flat->path[read];
      }
      write++;
    } else {
      zx_handle_close(flat->handle[read]);
      flat->handle[read] = ZX_HANDLE_INVALID;
    }
  }
  flat->count = write;
}

zx_status_t spawn_vmo_impl(zx_handle_t job, uint32_t flags, zx::vmo executable_vmo,
                           const char* const* argv, const char* const* explicit_environ,
                           SpawnActions& spawn_actions, zx_handle_t* process_out, char* err_msg) {
  // We intentionally don't fill in |err_msg| for invalid args.
  if (!executable_vmo.is_valid() || !argv) {
    return ZX_ERR_INVALID_ARGS;
  }

  if (job == ZX_HANDLE_INVALID)
    job = zx_job_default();

  const char* process_name = argv[0];
  size_t process_name_size = 0;
  std::vector<std::string_view> shared_dirs;

  // Do a first pass over the actions and flags to calculate how many handles
  // and namespace entries to send. In the second pass later, we would allocate
  // data structures bespoke to that size.
  size_t handle_capacity = 0;
  size_t name_count = 0;
  for (const auto& action : spawn_actions) {
    switch (action.action) {
      case FDIO_SPAWN_ACTION_CLONE_FD:
      case FDIO_SPAWN_ACTION_TRANSFER_FD:
        ++handle_capacity;
        break;
      case FDIO_SPAWN_ACTION_ADD_NS_ENTRY:
        if (action.ns.handle == ZX_HANDLE_INVALID || !action.ns.prefix) {
          return ZX_ERR_INVALID_ARGS;
        }
        ++name_count;
        break;
      case FDIO_SPAWN_ACTION_ADD_HANDLE:
        if (action.h.handle == ZX_HANDLE_INVALID) {
          return ZX_ERR_INVALID_ARGS;
        }
        if (action.h.id == PA_CLOCK_UTC) {
          // A UTC Clock handle is explicitly passed in.
          if ((flags & FDIO_SPAWN_CLONE_UTC_CLOCK) != 0) {
            report_error(err_msg, "cannot clone global UTC clock and send explicit clock");
            return ZX_ERR_INVALID_ARGS;
          }
        }
        ++handle_capacity;
        break;
      case FDIO_SPAWN_ACTION_SET_NAME:
        if (action.name.data == nullptr) {
          return ZX_ERR_INVALID_ARGS;
        }
        process_name = action.name.data;
        break;
      case FDIO_SPAWN_ACTION_CLONE_DIR: {
        if (!action.dir.prefix) {
          return ZX_ERR_INVALID_ARGS;
        }
        // The path must be absolute (rooted at '/') and not contain a trailing '/', but do
        // allow the root namespace to be specified as "/".
        size_t len = strlen(action.dir.prefix);
        if (len == 0 || action.dir.prefix[0] != '/' ||
            (len > 1 && action.dir.prefix[len - 1] == '/')) {
          return ZX_ERR_INVALID_ARGS;
        } else if (len == 1 && action.dir.prefix[0] == '/') {
          flags |= FDIO_SPAWN_CLONE_NAMESPACE;
        } else {
          shared_dirs.push_back(action.dir.prefix);
        }
      } break;
      default:
        break;
    }
  }

  if (!process_name) {
    return ZX_ERR_INVALID_ARGS;
  }

  if ((flags & FDIO_SPAWN_CLONE_JOB) != 0)
    ++handle_capacity;

  // Need to clone ldsvc here so it's available for handle_interpreters.
  zx::channel ldsvc;
  zx_status_t status = ZX_OK;
  if ((flags & FDIO_SPAWN_DEFAULT_LDSVC) != 0) {
    status = dl_clone_loader_service(ldsvc.reset_and_get_address());
    if (status != ZX_OK) {
      report_error(err_msg, "failed to clone library loader service: %d (%s)", status,
                   zx_status_get_string(status));
      return status;
    }
  }

  if ((flags & FDIO_SPAWN_CLONE_STDIO) != 0)
    handle_capacity += 3;

  zx_handle_t utc_clock = ZX_HANDLE_INVALID;
  if ((flags & FDIO_SPAWN_CLONE_UTC_CLOCK) != 0) {
    utc_clock = zx_utc_reference_get();
    if (utc_clock != ZX_HANDLE_INVALID) {
      ++handle_capacity;
    }
  }

  fprocess::wire::LaunchInfo launch_info = {
      .executable = std::move(executable_vmo),
  };
  std::list<std::string> extra_args;
  // resolve any '#!' directives that are present, updating executable and ldsvc as needed
  status = handle_interpreters(&launch_info.executable, &ldsvc, &extra_args, err_msg);
  if (status != ZX_OK) {
    return status;
  }
  if (ldsvc.is_valid()) {
    ++handle_capacity;
  }

  zx::status launcher_endpoints = fidl::CreateEndpoints<fprocess::Launcher>();
  if (!launcher_endpoints.is_ok()) {
    report_error(err_msg, "failed to create channel for launcher service: %d",
                 launcher_endpoints.status_value());
    return status;
  }
  fidl::WireSyncClient launcher{std::move(launcher_endpoints->client)};
  status = fdio_service_connect_by_name(fidl::DiscoverableProtocolName<fprocess::Launcher>,
                                        launcher_endpoints->server.TakeChannel().release());
  if (status != ZX_OK) {
    report_error(err_msg, "failed to connect to launcher service: %d (%s)", status,
                 zx_status_get_string(status));
    return status;
  }

  // send any extra arguments from handle_interpreters, then the normal arguments.
  {
    size_t capacity = extra_args.size();
    for (auto it = argv; *it; ++it) {
      ++capacity;
    }

    std::vector<fidl::VectorView<uint8_t>> args;
    args.reserve(capacity);
    for (const auto& arg : extra_args) {
      auto ptr = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(arg.data()));
      args.emplace_back(fidl::VectorView<uint8_t>::FromExternal(ptr, arg.length()));
    }
    for (auto it = argv; *it; ++it) {
      auto ptr = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(*it));
      args.emplace_back(fidl::VectorView<uint8_t>::FromExternal(ptr, strlen(*it)));
    }

    status =
        launcher->AddArgs(fidl::VectorView<fidl::VectorView<uint8_t>>::FromExternal(args)).status();
    if (status != ZX_OK) {
      report_error(err_msg, "failed to send argument vector: %d (%s)", status,
                   zx_status_get_string(status));
      return status;
    }
  }

  if (explicit_environ) {
    size_t capacity = 0;
    for (auto it = explicit_environ; *it; ++it) {
      ++capacity;
    }
    std::vector<fidl::VectorView<uint8_t>> env;
    env.reserve(capacity);
    for (auto it = explicit_environ; *it; ++it) {
      auto ptr = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(*it));
      env.emplace_back(fidl::VectorView<uint8_t>::FromExternal(ptr, strlen(*it)));
    }
    status = launcher->AddEnvirons(fidl::VectorView<fidl::VectorView<uint8_t>>::FromExternal(env))
                 .status();
    if (status != ZX_OK) {
      report_error(err_msg, "failed to send environment: %d (%s)", status,
                   zx_status_get_string(status));
      return status;
    }
  } else if ((flags & FDIO_SPAWN_CLONE_ENVIRON) != 0) {
    size_t capacity = 0;
    for (auto it = environ; *it; ++it) {
      ++capacity;
    }
    std::vector<fidl::VectorView<uint8_t>> env;
    env.reserve(capacity);
    for (auto it = environ; *it; ++it) {
      auto ptr = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(*it));
      env.emplace_back(fidl::VectorView<uint8_t>::FromExternal(ptr, strlen(*it)));
    }
    status = launcher->AddEnvirons(fidl::VectorView<fidl::VectorView<uint8_t>>::FromExternal(env))
                 .status();
    if (status != ZX_OK) {
      report_error(err_msg, "failed to send environment clone with FDIO_SPAWN_CLONE_ENVIRON: %d",
                   status);
      return status;
    }
  }

  fdio_flat_namespace_t* flat = nullptr;
  auto flat_namespace_cleanup = fit::defer([&flat] {
    if (flat) {
      fdio_ns_free_flat_ns(flat);
    }
  });

  if (!shared_dirs.empty() || (flags & FDIO_SPAWN_CLONE_NAMESPACE) != 0) {
    status = fdio_ns_export_root(&flat);
    if (status != ZX_OK) {
      report_error(err_msg, "Could not make copy of root namespace: %d (%s)", status,
                   zx_status_get_string(status));
      return status;
    }

    // If we don't clone the entire namespace, we need to filter down to only the
    // directories that are prefixed by paths in FDIO_SPAWN_ACTION_CLONE_DIR actions.
    if ((flags & FDIO_SPAWN_CLONE_NAMESPACE) == 0) {
      filter_flat_namespace(flat, shared_dirs);
    }

    name_count += flat->count;
  }

  status = send_handles_and_namespace(launcher, handle_capacity, flags, job, std::move(ldsvc),
                                      utc_clock, name_count, flat,
                                      std::move(spawn_actions).ConsumeWhileIterating(), err_msg);
  if (status != ZX_OK) {
    return status;
  }

  process_name_size = strlen(process_name);
  if (process_name_size >= ZX_MAX_NAME_LEN)
    process_name_size = ZX_MAX_NAME_LEN - 1;

  launch_info.name = fidl::StringView::FromExternal(process_name, process_name_size);
  status = zx_handle_duplicate(job, ZX_RIGHT_SAME_RIGHTS, launch_info.job.reset_and_get_address());
  if (status != ZX_OK) {
    report_error(err_msg, "failed to duplicate job handle: %d (%s)", status,
                 zx_status_get_string(status));
    return status;
  }

  fidl::WireResult reply = launcher->Launch(std::move(launch_info));
  status = reply.status();
  if (status != ZX_OK) {
    report_error(err_msg, "failed to send launch message: %d (%s)", status,
                 zx_status_get_string(status));
    return status;
  }

  status = reply->status;
  if (status != ZX_OK) {
    report_error(err_msg, "fuchsia.process.Launcher failed");
    return status;
  }

  // The launcher claimed to succeed but didn't actually give us a
  // process handle. Something is wrong with the launcher.
  if (!reply->process.is_valid()) {
    report_error(err_msg, "failed receive process handle");
    return ZX_ERR_BAD_HANDLE;
  }

  if (process_out) {
    *process_out = reply->process.release();
  }

  return ZX_OK;
}

}  // namespace

__EXPORT
zx_status_t fdio_spawn_vmo(zx_handle_t job, uint32_t flags, zx_handle_t executable_vmo,
                           const char* const* argv, const char* const* explicit_environ,
                           size_t action_count, const fdio_spawn_action_t* actions,
                           zx_handle_t* process_out, char* err_msg) {
  zx::vmo executable(executable_vmo);
  if (err_msg)
    err_msg[0] = '\0';

  if (action_count > 0 && !actions) {
    return ZX_ERR_INVALID_ARGS;
  }

  SpawnActions spawn_actions(actions, action_count);
  zx_status_t status = spawn_vmo_impl(job, flags, std::move(executable), argv, explicit_environ,
                                      spawn_actions, process_out, err_msg);

  // If we observe ZX_ERR_NOT_FOUND in the VMO spawn, it really means a
  // dependency of launching could not be fulfilled, but clients of spawn_etc
  // and friends could misinterpret this to mean the binary was not found.
  // Instead we remap that specific case to ZX_ERR_INTERNAL.
  if (status == ZX_ERR_NOT_FOUND) {
    return ZX_ERR_INTERNAL;
  }

  return status;
}
