// 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 <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/stdcompat/string_view.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>

namespace fio = fuchsia_io;
namespace fprocess = fuchsia_process;

constexpr std::string_view kResolvePrefix = "#!resolve ";

// 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.
constexpr size_t kMaxInterpreterDepth = 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.
constexpr size_t kMaxInterpreterLineLen =
    kResolvePrefix.size() + fprocess::wire::kMaxResolveNameSize;
static_assert(kMaxInterpreterLineLen < ZX_MIN_PAGE_SIZE,
              "max #! interpreter line length must be less than smallest page size");

// 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::result 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.value().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.value().executable);
  *out_ldsvc = std::move(response.value().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[kMaxInterpreterLineLen];
    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 == kMaxInterpreterDepth) {
      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 (cpp20::starts_with(std::string_view(line, line_len), kResolvePrefix)) {
      // 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[kResolvePrefix.size()];
      size_t name_len = line_len - kResolvePrefix.size();
      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) {}

    ~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_ = 0;
  };

  // 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), 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_ = 0;
  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) {
  // 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;
    if (zx_status_t status = zx_handle_duplicate(job, ZX_RIGHT_SAME_RIGHTS,
                                                 handle_info->handle.reset_and_get_address());
        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: {
        if (zx_status_t status = check_fd(action->fd.target_fd); 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;
        }
        zx_handle_t fd_handle;
        if (zx_status_t status = fdio_fd_clone(action->fd.local_fd, &fd_handle); 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: {
        if (zx_status_t status = check_fd(action->fd.target_fd); 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;
        }
        zx_handle_t fd_handle;
        if (zx_status_t status = fdio_fd_transfer(action->fd.local_fd, &fd_handle);
            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;
          if (zx_status_t status = check_fd(fd); 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;
      if (zx_status_t status = fdio_fd_clone(fd, &fd_handle); status != ZX_OK) {
        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;
        }
        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;
      if (zx_status_t 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());
          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);
  if (zx_status_t status = launcher->AddHandles(handle_infos.vector_view()).status();
      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);
  if (zx_status_t status = launcher->AddNames(names.vector_view()).status(); 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) {
  return std::any_of(prefixes.begin(), prefixes.end(), [path](const std::string_view& prefix) {
    // 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.
    return (cpp20::starts_with(path, prefix) &&
            (path.size() == prefix.size() || path[prefix.size()] == '/'));
  });
}

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];
        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;
        }
        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;
  if ((flags & FDIO_SPAWN_DEFAULT_LDSVC) != 0) {
    if (zx_status_t status = dl_clone_loader_service(ldsvc.reset_and_get_address());
        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
  if (zx_status_t status =
          handle_interpreters(&launch_info.executable, &ldsvc, &extra_args, err_msg);
      status != ZX_OK) {
    return status;
  }
  if (ldsvc.is_valid()) {
    ++handle_capacity;
  }

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

    if (zx_status_t status =
            launcher->AddArgs(fidl::VectorView<fidl::VectorView<uint8_t>>::FromExternal(args))
                .status();
        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)));
    }
    if (zx_status_t status =
            launcher->AddEnvirons(fidl::VectorView<fidl::VectorView<uint8_t>>::FromExternal(env))
                .status();
        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)));
    }
    if (zx_status_t status =
            launcher->AddEnvirons(fidl::VectorView<fidl::VectorView<uint8_t>>::FromExternal(env))
                .status();
        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) {
    if (zx_status_t status = fdio_ns_export_root(&flat); 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;
  }

  if (zx_status_t 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);
      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);
  if (zx_status_t status =
          zx_handle_duplicate(job, ZX_RIGHT_SAME_RIGHTS, launch_info.job.reset_and_get_address());
      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));
  if (zx_status_t status = reply.status(); status != ZX_OK) {
    report_error(err_msg, "failed to send launch message: %d (%s)", status,
                 zx_status_get_string(status));
    return status;
  }

  if (zx_status_t status = reply.value().status; 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.value().process.is_valid()) {
    report_error(err_msg, "failed receive process handle");
    return ZX_ERR_BAD_HANDLE;
  }

  if (process_out) {
    *process_out = reply.value().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;
}
