// Copyright 2020 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/lib/loader_service/loader_service.h"

#include <fuchsia/io/llcpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/io.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/errors.h>

#include "src/lib/files/path.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace loader {

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

LoaderServiceBase::~LoaderServiceBase() {}

const std::string& LoaderServiceBase::log_prefix() {
  if (log_prefix_.empty()) {
    log_prefix_ = fxl::StringPrintf("ldsvc (%s): ", name_.data());
  }
  return log_prefix_;
}

zx::status<zx::channel> LoaderServiceBase::Connect() {
  zx::channel c1, c2;
  auto status = zx::make_status(zx::channel::create(0, &c1, &c2));
  if (status.is_error()) {
    return status.take_error();
  }
  status = Bind(std::move(c1));
  if (status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::move(c2));
}

zx::status<> LoaderServiceBase::Bind(zx::channel channel) {
  // Each connection gets a strong (shared_ptr) reference to the server, which keeps the overall
  // service alive as long as there is one open connection even if the original reference is
  // dropped.
  auto conn = std::make_unique<LoaderConnection>(shared_from_this());
  // This returns a ServerBindingRef on success, but we don't need it since we don't currently need
  // a way to unbind connections from the server side. Dropping it does not automatically unbind.
  auto status = fidl::BindServer(dispatcher_, std::move(channel), std::move(conn));
  if (status.is_error()) {
    return zx::error(status.take_error());
  }
  return zx::ok();
}

void LoaderConnection::Done(DoneCompleter::Sync& completer) { completer.Close(ZX_OK); }

void LoaderConnection::LoadObject(fidl::StringView object_name,
                                  LoadObjectCompleter::Sync& completer) {
  std::string name(object_name.data(), object_name.size());

  auto reply = [this, &name, &completer](zx::status<zx::vmo> status) {
    // Generally we wouldn't want to log in a library, but these logs have proven to be useful in
    // past, and the new loader name in the prefix will make them moreso.
    if (status.status_value() == ZX_ERR_NOT_FOUND) {
      FX_LOGS(WARNING) << log_prefix() << "could not find '" << name << "'";
    }

    auto result = completer.Reply(status.status_value(), std::move(status).value_or(zx::vmo()));
    if (!result.ok()) {
      FX_LOGS(WARNING) << log_prefix() << "failed to reply to LoadObject(" << name
                       << "): " << result.status_string() << " (" << result.error() << ')';
    }
  };

  if (config_.subdir.empty()) {
    reply(server_->LoadObjectImpl(name));
    return;
  }

  // If subdir is non-empty, the loader should search this subdirectory for the object first. If
  // exclusive is also true, only subdir should be searched.
  std::string prefixed_name = files::JoinPath(config_.subdir, name);
  auto status = server_->LoadObjectImpl(prefixed_name);
  if (status.is_error() && !config_.exclusive) {
    reply(server_->LoadObjectImpl(name));
    return;
  }
  reply(std::move(status));
}

void LoaderConnection::Config(fidl::StringView config, ConfigCompleter::Sync& completer) {
  // fidl::StringView is not null-terminated so must pass size to std::string constructor.
  std::string config_str(config.data(), config.size());

  auto reply = [this, &config_str, &completer](zx_status_t status) {
    auto result = completer.Reply(status);
    if (!result.ok()) {
      FX_LOGS(WARNING) << log_prefix() << "failed to reply to Config(" << config_str
                       << "): " << result.status_string() << " (" << result.error() << ')';
    }
  };

  // Config strings must not contain path separators.
  if (config_str.find('/') != std::string::npos) {
    reply(ZX_ERR_INVALID_ARGS);
    return;
  }

  // The config string is a single subdirectory name to be searched for objects first, optionally
  // followed by a '!' character, which indicates that only the subdirectory should be searched.
  bool exclusive = false;
  if (!config_str.empty() && config_str.back() == '!') {
    exclusive = true;
    config_str.pop_back();

    // Make sure config wasn't "!" (though just "" is ok to reset config)
    if (config_str.empty()) {
      reply(ZX_ERR_INVALID_ARGS);
      return;
    }
  }
  config_ = LoadConfig{.subdir = config_str, .exclusive = exclusive};
  reply(ZX_OK);
}

void LoaderConnection::Clone(zx::channel loader, CloneCompleter::Sync& completer) {
  completer.Reply(server_->Bind(std::move(loader)).status_value());
}

// static
std::shared_ptr<LoaderService> LoaderService::Create(async_dispatcher_t* dispatcher,
                                                     fbl::unique_fd lib_dir, std::string name) {
  // Can't use make_shared because constructor is protected
  return std::shared_ptr<LoaderService>(
      new LoaderService(dispatcher, std::move(lib_dir), std::move(name)));
}

zx::status<zx::vmo> LoaderService::LoadObjectImpl(std::string path) {
  const uint32_t kFlags =
      fio::OPEN_FLAG_NOT_DIRECTORY | fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_EXECUTABLE;

  fbl::unique_fd fd;
  zx_status_t status = fdio_open_fd_at(dir_.get(), path.data(), kFlags, fd.reset_and_get_address());
  if (status != ZX_OK) {
    return zx::error(status);
  }

  zx::vmo vmo;
  status = fdio_get_vmo_exec(fd.get(), vmo.reset_and_get_address());
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(std::move(vmo));
}

}  // namespace loader
