// 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<fidl::ClientEnd<llcpp::fuchsia::ldsvc::Loader>> LoaderServiceBase::Connect() {
  auto endpoints = fidl::CreateEndpoints<llcpp::fuchsia::ldsvc::Loader>();
  if (endpoints.is_error()) {
    return endpoints.take_error();
  }
  auto [client, server] = *std::move(endpoints);
  auto status = Bind(std::move(server));
  if (status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::move(client));
}

zx::status<> LoaderServiceBase::Bind(fidl::ServerEnd<llcpp::fuchsia::ldsvc::Loader> 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(fidl::ServerEnd<llcpp::fuchsia::ldsvc::Loader> 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
