// 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 <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/device/vfs.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(), ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE,
                     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(), ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE,
                     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
