// 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/sys/lib/chrealm/chrealm.h"

#include <fcntl.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/spawn.h>
#include <lib/fit/defer.h>
#include <lib/zx/job.h>
#include <unistd.h>
#include <zircon/compiler.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <cstdio>
#include <cstdlib>
#include <string>

#include "lib/fidl/cpp/interface_request.h"
#include "src/lib/fxl/strings/concatenate.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace chrealm {

zx_status_t RunBinaryInRealm(const std::string& realm_path, const char** argv, int64_t* return_code,
                             std::string* error) {
  *return_code = -1;
  zx_handle_t proc;
  zx_status_t status =
      SpawnBinaryInRealmAsync(realm_path, argv, ZX_HANDLE_INVALID,
                              FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_NAMESPACE, {}, &proc, error);
  if (status != ZX_OK) {
    return status;
  }
  status = zx_object_wait_one(proc, ZX_PROCESS_TERMINATED, ZX_TIME_INFINITE, nullptr);
  if (status != ZX_OK) {
    *error = "Could not wait for command";
    return status;
  }
  zx_info_process_t info;
  status = zx_object_get_info(proc, ZX_INFO_PROCESS, &info, sizeof(info), nullptr, nullptr);
  if (status != ZX_OK) {
    *error = "Could not get result of command";
    return status;
  }

  *return_code = info.return_code;
  return ZX_OK;
}

zx_status_t SpawnBinaryInRealmAsync(const std::string& realm_path, const char** argv,
                                    zx_handle_t job, int32_t flags,
                                    const std::vector<fdio_spawn_action_t>& additional_actions,
                                    zx_handle_t* proc, std::string* error) {
  if (flags & FDIO_SPAWN_CLONE_NAMESPACE) {
    *error = "chrealm does not support FDIO_SPAWN_CLONE_NAMESPACE";
    return ZX_ERR_INVALID_ARGS;
  }
  error->clear();

  // Open the provided path, which is the realm's hub directory.
  zx::channel realm_hub_dir, realm_hub_server;
  zx_status_t status = zx::channel::create(0, &realm_hub_dir, &realm_hub_server);
  if (status != ZX_OK) {
    *error = "Could not create channel";
    return status;
  }
  status = fdio_open(realm_path.c_str(),
                     static_cast<uint32_t>(fuchsia_io::wire::OpenFlags::kRightReadable |
                                           fuchsia_io::wire::OpenFlags::kRightWritable),
                     realm_hub_server.release());
  if (status != ZX_OK) {
    *error = fxl::StringPrintf("Could not open hub in realm: %s", realm_path.c_str());
    return status;
  }

  // Open the services dir in the realm's hub directory.
  zx::channel realm_svc_dir, realm_svc_server;
  status = zx::channel::create(0, &realm_svc_dir, &realm_svc_server);
  if (status != ZX_OK) {
    *error = "Could not create channel";
    return status;
  }
  const std::string svc_path = fxl::Concatenate({realm_path, "/svc"});
  status = fdio_open(svc_path.c_str(),
                     static_cast<uint32_t>(fuchsia_io::wire::OpenFlags::kRightReadable |
                                           fuchsia_io::wire::OpenFlags::kRightWritable),
                     realm_svc_server.release());
  if (status != ZX_OK) {
    *error = fxl::StringPrintf("Could not open svc in realm: %s", svc_path.c_str());
    return status;
  }

  zx::job realm_job;
  if (!job) {
    // Open the realm's job.
    fuchsia::sys::JobProviderSyncPtr job_provider;
    status = fdio_service_connect_at(realm_hub_dir.get(), "job",
                                     job_provider.NewRequest().TakeChannel().release());
    if (status != ZX_OK) {
      *error = fxl::StringPrintf("Could not connect to job provider: %s", svc_path.c_str());
      return status;
    }
    status = job_provider->GetJob(&realm_job);
    if (status == ZX_OK && !realm_job) {
      status = ZX_ERR_INTERNAL;
    }
    if (status != ZX_OK) {
      *error = "Could not get realm job";
      return status;
    }
    job = realm_job.get();
  }

  // Convert 'ns' to a flat namespace and replace /svc and /hub.
  fdio_flat_namespace_t* flat_ns = nullptr;
  status = fdio_ns_export_root(&flat_ns);
  if (status != ZX_OK) {
    *error = "Could not flatten namespace";
    return status;
  }
  auto cleanup = fit::defer([&flat_ns]() { fdio_ns_free_flat_ns(flat_ns); });

  size_t action_count = flat_ns->count + additional_actions.size();
  fdio_spawn_action_t actions[action_count];
  for (size_t i = 0; i < flat_ns->count; ++i) {
    zx_handle_t handle;
    if (std::string(flat_ns->path[i]) == "/svc") {
      handle = realm_svc_dir.release();
    } else if (std::string(flat_ns->path[i]) == "/hub") {
      handle = realm_hub_dir.release();
    } else {
      handle = flat_ns->handle[i];
    }
    fdio_spawn_action_t add_ns_entry = {
        .action = FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
        .ns =
            {
                .prefix = flat_ns->path[i],
                .handle = handle,
            },
    };
    actions[i] = add_ns_entry;
  }
  for (size_t i = 0; i < additional_actions.size(); ++i) {
    actions[flat_ns->count + i] = additional_actions[i];
  }

  // Launch the binary.
  const char* binary_path = argv[0];
  char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
  status = fdio_spawn_etc(job, flags & ~FDIO_SPAWN_CLONE_NAMESPACE, binary_path, argv, nullptr,
                          action_count, actions, proc, err_msg);
  if (status != ZX_OK) {
    *error = fxl::StringPrintf("Failed to launch command: %s", err_msg);
    return status;
  }

  return ZX_OK;
}

}  // namespace chrealm
