// Copyright 2017 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/storage/fshost/pkgfs-launcher.h"

#include <fuchsia/io/llcpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/channel.h>
#include <lib/zx/process.h>
#include <stdio.h>
#include <zircon/errors.h>
#include <zircon/processargs.h>

#include "src/storage/fshost/fdio.h"
#include "src/storage/fshost/filesystem-mounter.h"
#include "src/storage/fshost/fshost-fs-provider.h"
#include "src/storage/fshost/pkgfs-loader-service.h"

namespace fio = ::llcpp::fuchsia::io;

namespace devmgr {

namespace {

zx::status<> WaitForPkgfsLaunchCompletion(zx::process proc) {
  auto deadline = zx::deadline_after(zx::sec(100));
  zx_signals_t observed;
  auto status =
      zx::make_status(proc.wait_one(ZX_USER_SIGNAL_0 | ZX_PROCESS_TERMINATED, deadline, &observed));
  if (status.is_error()) {
    FX_LOGS(ERROR) << "pkgfs did not signal completion: " << status.status_string();
    return status;
  }
  if (!(observed & ZX_USER_SIGNAL_0)) {
    FX_LOGS(ERROR) << "pkgfs terminated prematurely";
    return zx::error(ZX_ERR_BAD_STATE);
  }
  return zx::ok();
}

zx::status<> FinishPkgfsLaunch(FilesystemMounter* filesystems, zx::channel pkgfs_root) {
  // re-export /pkgfs/system as /system
  zx::channel system_channel, system_req;
  zx_status_t status = zx::channel::create(0, &system_channel, &system_req);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  status = fdio_open_at(pkgfs_root.get(), "system", FS_READ_EXEC_DIR_FLAGS, system_req.release());
  if (status != ZX_OK) {
    return zx::error(status);
  }
  // re-export /pkgfs/packages/shell-commands/0/bin as /bin
  zx::channel bin_chan, bin_req;
  status = zx::channel::create(0, &bin_chan, &bin_req);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  status = fdio_open_at(pkgfs_root.get(), "packages/shell-commands/0/bin", FS_READ_EXEC_DIR_FLAGS,
                        bin_req.release());
  if (status != ZX_OK) {
    // non-fatal.
    FX_LOGS(ERROR) << "failed to install /bin (could not open shell-commands)";
  }
  status = filesystems->InstallFs("/pkgfs", std::move(pkgfs_root));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to install /pkgfs";
    return zx::error(status);
  }
  status = filesystems->InstallFs("/system", std::move(system_channel));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to install /system";
    return zx::error(status);
  }
  // as above, failure of /bin export is non-fatal.
  status = filesystems->InstallFs("/bin", std::move(bin_chan));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to install /bin";
  }
  // start the delayed vfs
  filesystems->FuchsiaStart();
  return zx::ok();
}

}  // namespace

zx::status<> LaunchPkgfs(FilesystemMounter* filesystems) {
  // Get the pkgfs.cmd boot argument
  auto cmd_status = filesystems->boot_args()->pkgfs_cmd();
  if (cmd_status.is_error()) {
    FX_LOGS(ERROR) << "unable to launch pkgfs, missing \"zircon.system.pkgfs.cmd\" boot argument";
    return zx::error(ZX_ERR_INVALID_ARGS);
  }
  const char* cmd = cmd_status.value().c_str();

  fbl::unique_fd blob_dir;
  auto status = zx::make_status(fdio_open_fd("/fs/blob",
                                             fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_EXECUTABLE,
                                             blob_dir.reset_and_get_address()));
  if (status.is_error()) {
    FX_LOGS(ERROR) << "fdio_open_fd(/fs/blob) failed: " << status.status_string();
    return status;
  }

  auto args = ArgumentVector::FromCmdline(cmd);
  auto argv = args.argv();
  // Remove leading slashes before asking pkgfs_ldsvc_load_blob to load the
  // file.
  const char* file = argv[0];
  while (file[0] == '/') {
    ++file;
  }

  auto loader = PkgfsLoaderService::Create(std::move(blob_dir), filesystems->boot_args());
  auto executable = loader->LoadPkgfsFile(argv[0]);
  if (executable.is_error()) {
    FX_LOGS(ERROR) << "cannot load pkgfs executable: " << executable.status_string();
    return executable.take_error();
  }

  auto loader_conn = loader->Connect();
  if (loader_conn.is_error()) {
    FX_LOGS(ERROR) << "failed to connect to pkgfs loader: " << loader_conn.status_string();
    return loader_conn.take_error();
  }

  zx::channel h0, h1;
  status = zx::make_status(zx::channel::create(0, &h0, &h1));
  if (status.is_error()) {
    FX_LOGS(ERROR) << "cannot create pkgfs root channel: " << status.status_string();
    return status;
  }

  const zx_handle_t handles[] = {h1.release()};
  const uint32_t handle_types[] = {PA_HND(PA_USER0, 0)};
  size_t hcount = sizeof(handles) / sizeof(*handles);
  zx::process proc;
  FX_LOGS(INFO) << "starting " << args << "...";

  FshostFsProvider fs_provider;
  DevmgrLauncher launcher(&fs_provider);
  status = zx::make_status(
      launcher.LaunchWithLoader(*zx::job::default_job(), "pkgfs", std::move(executable).value(),
                                std::move(loader_conn).value(), argv, nullptr, -1,
                                /* TODO(fxbug.dev/32044) */ zx::resource(), handles, handle_types,
                                hcount, &proc, FS_DATA | FS_BLOB_EXEC | FS_SVC));
  if (status.is_error()) {
    FX_LOGS(ERROR) << "failed to launch " << cmd << ": " << status.status_string();
    return status;
  }

  status = WaitForPkgfsLaunchCompletion(std::move(proc));
  if (status.is_error()) {
    return status;
  }
  return FinishPkgfsLaunch(filesystems, std::move(h0));
}

}  // namespace devmgr
