// 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/storage/blobfs/query.h"

#include <lib/fidl-async/cpp/bind.h>

#include <blobfs/format.h>

#include "src/storage/blobfs/blobfs.h"
#include "src/storage/blobfs/runner.h"

namespace fuchsia_fs = ::llcpp::fuchsia::fs;

namespace blobfs {

constexpr const char kFsName[] = "blobfs";

QueryService::QueryService(async_dispatcher_t* dispatcher, Blobfs* blobfs, Runner* runner)
    : fs::Service([dispatcher, this](zx::channel server_end) {
        return fidl::BindSingleInFlightOnly(dispatcher, std::move(server_end), this);
      }),
      blobfs_(blobfs),
      runner_(runner) {}

void QueryService::GetInfo(fuchsia_fs::FilesystemInfoQuery query,
                           GetInfoCompleter::Sync& completer) {
  static_assert(fbl::constexpr_strlen(kFsName) < fuchsia_fs::MAX_FS_NAME_LENGTH,
                "Blobfs name too long");

  fuchsia_fs::FilesystemInfo::UnownedBuilder builder;

  uint64_t total_bytes;
  if (query & fuchsia_fs::FilesystemInfoQuery::TOTAL_BYTES) {
    total_bytes = blobfs_->Info().data_block_count * blobfs_->Info().block_size;
    builder.set_total_bytes(fidl::unowned_ptr(&total_bytes));
  }

  uint64_t used_bytes;
  if (query & fuchsia_fs::FilesystemInfoQuery::USED_BYTES) {
    used_bytes = blobfs_->Info().alloc_block_count * blobfs_->Info().block_size;
    builder.set_used_bytes(fidl::unowned_ptr(&used_bytes));
  }

  uint64_t total_nodes;
  if (query & fuchsia_fs::FilesystemInfoQuery::TOTAL_NODES) {
    total_nodes = blobfs_->Info().inode_count;
    builder.set_total_nodes(fidl::unowned_ptr(&total_nodes));
  }

  uint64_t used_nodes;
  if (query & fuchsia_fs::FilesystemInfoQuery::USED_NODES) {
    used_nodes = blobfs_->Info().alloc_inode_count;
    builder.set_used_nodes(fidl::unowned_ptr(&used_nodes));
  }

  zx::event fs_id;
  if (query & fuchsia_fs::FilesystemInfoQuery::FS_ID) {
    zx_status_t status = blobfs_->GetFsId(&fs_id);
    if (status != ZX_OK) {
      completer.ReplyError(status);
      return;
    }
    builder.set_fs_id(fidl::unowned_ptr(&fs_id));
  }

  uint32_t block_size;
  if (query & fuchsia_fs::FilesystemInfoQuery::BLOCK_SIZE) {
    block_size = kBlobfsBlockSize;
    builder.set_block_size(fidl::unowned_ptr(&block_size));
  }

  uint32_t max_node_name_size;
  if (query & fuchsia_fs::FilesystemInfoQuery::MAX_NODE_NAME_SIZE) {
    max_node_name_size = digest::kSha256HexLength;
    builder.set_max_node_name_size(fidl::unowned_ptr(&max_node_name_size));
  }

  fuchsia_fs::FsType fs_type;
  if (query & fuchsia_fs::FilesystemInfoQuery::FS_TYPE) {
    fs_type = fuchsia_fs::FsType::BLOBFS;
    builder.set_fs_type(fidl::unowned_ptr(&fs_type));
  }

  fidl::StringView name;
  if (query & fuchsia_fs::FilesystemInfoQuery::NAME) {
    name = fidl::StringView(kFsName);
    builder.set_name(fidl::unowned_ptr(&name));
  }

  fidl::StringView device_path;
  char name_buf[llcpp::fuchsia::io2::MAX_PATH_LENGTH];
  size_t name_len;
  if (query & fuchsia_fs::FilesystemInfoQuery::DEVICE_PATH) {
    zx_status_t status =
        blobfs_->Device()->GetDevicePath(llcpp::fuchsia::io2::MAX_PATH_LENGTH, name_buf, &name_len);
    if (status != ZX_OK) {
      completer.ReplyError(status);
      return;
    }
    // It appears that the |name_len| returned by |GetDevicePath| includes a trailing NUL.
    ZX_ASSERT(name_buf[name_len - 1] == '\0');
    device_path = fidl::StringView(name_buf, name_len - 1);
    builder.set_device_path(fidl::unowned_ptr(&device_path));
  }

  completer.ReplySuccess(builder.build());
}

void QueryService::IsNodeInFilesystem(zx::event token,
                                      IsNodeInFilesystemCompleter::Sync& completer) {
  completer.Reply(runner_->IsTokenAssociatedWithVnode(std::move(token)));
}

}  // namespace blobfs
