// 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/fs_test/fs_test.h"

#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <fidl/fuchsia.device/cpp/wire.h>
#include <fidl/fuchsia.fs/cpp/wire.h>
#include <fidl/fuchsia.hardware.ramdisk/cpp/wire.h>
#include <fuchsia/fs/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/device-watcher/cpp/device-watcher.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/namespace.h>
#include <lib/fidl/cpp/wire/connect_service.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/sync/completion.h>
#include <lib/zx/channel.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <zircon/errors.h>

#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <utility>

#include <fbl/unique_fd.h>

#include "sdk/lib/syslog/cpp/macros.h"
#include "src/lib/json_parser/json_parser.h"
#include "src/storage/blobfs/blob_layout.h"
#include "src/storage/fs_test/blobfs_test.h"
#include "src/storage/fs_test/json_filesystem.h"
#include "src/storage/lib/fs_management/cpp/admin.h"
#include "src/storage/lib/fs_management/cpp/format.h"
#include "src/storage/lib/fs_management/cpp/fvm.h"
#include "src/storage/lib/fs_management/cpp/mkfs_with_default.h"
#include "src/storage/lib/fs_management/cpp/mount.h"
#include "src/storage/testing/fvm.h"

namespace fs_test {
namespace {

/// Amount of time to wait for a given device to be available.
constexpr zx::duration kDeviceWaitTime = zx::sec(30);

// Creates a ram-disk with an optional FVM partition. Returns the ram-disk and the device path.
zx::result<std::pair<storage::RamDisk, std::string>> CreateRamDisk(
    const TestFilesystemOptions& options) {
  if (options.use_ram_nand) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  zx::vmo vmo;
  if (options.vmo->is_valid()) {
    uint64_t vmo_size;
    auto status = zx::make_result(options.vmo->get_size(&vmo_size));
    if (status.is_error()) {
      return status.take_error();
    }
    status = zx::make_result(options.vmo->create_child(ZX_VMO_CHILD_SLICE, 0, vmo_size, &vmo));
    if (status.is_error()) {
      return status.take_error();
    }
  } else {
    fzl::VmoMapper mapper;
    auto status =
        zx::make_result(mapper.CreateAndMap(options.device_block_size * options.device_block_count,
                                            ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &vmo));
    if (status.is_error()) {
      std::cout << "Unable to create VMO for ramdisk: " << status.status_string() << std::endl;
      return status.take_error();
    }

    // Fill the ram-disk with a non-zero value so that we don't inadvertently depend on it being
    // zero filled.
    if (!options.zero_fill) {
      memset(mapper.start(), 0xaf, mapper.size());
    }
  }

  // Create a ram-disk.
  auto ram_disk_or = storage::RamDisk::CreateWithVmo(std::move(vmo), options.device_block_size);
  if (ram_disk_or.is_error()) {
    return ram_disk_or.take_error();
  }

  if (options.fail_after) {
    if (auto status = ram_disk_or->SleepAfter(options.fail_after); status.is_error()) {
      return status.take_error();
    }
  }

  if (options.ram_disk_discard_random_after_last_flush) {
    uint32_t flags = static_cast<uint32_t>(
        fuchsia_hardware_ramdisk::wire::RamdiskFlag::kDiscardRandom |
        fuchsia_hardware_ramdisk::wire::RamdiskFlag::kDiscardNotFlushedOnWake);
    ramdisk_set_flags(ram_disk_or->client(), flags);
  }

  std::string device_path = ram_disk_or.value().path();
  return zx::ok(std::make_pair(std::move(ram_disk_or).value(), std::move(device_path)));
}

// Creates a ram-nand device.  It does not create an FVM partition; that is left to the caller.
zx::result<std::pair<ramdevice_client::RamNand, std::string>> CreateRamNand(
    const TestFilesystemOptions& options) {
  constexpr int kPageSize = 4096;
  constexpr int kPagesPerBlock = 64;
  constexpr int kOobSize = 8;

  uint32_t block_count;
  zx::vmo vmo;
  if (options.vmo->is_valid()) {
    uint64_t vmo_size;
    auto status = zx::make_result(options.vmo->get_size(&vmo_size));
    if (status.is_error()) {
      return status.take_error();
    }
    block_count = static_cast<uint32_t>(vmo_size / (kPageSize + kOobSize) / kPagesPerBlock);
    // For now, when using a ram-nand device, the only supported device block size is 8 KiB, so
    // raise an error if the user tries to ask for something different.
    if ((options.device_block_size != 0 && options.device_block_size != 8192) ||
        (options.device_block_count != 0 &&
         options.device_block_size * options.device_block_count !=
             block_count * kPageSize * kPagesPerBlock)) {
      std::cout << "Bad device parameters" << std::endl;
      return zx::error(ZX_ERR_INVALID_ARGS);
    }
    status = zx::make_result(options.vmo->create_child(ZX_VMO_CHILD_SLICE, 0, vmo_size, &vmo));
    if (status.is_error()) {
      return status.take_error();
    }
  } else if (options.device_block_size != 8192) {  // FTL exports a device with 8 KiB blocks.
    return zx::error(ZX_ERR_INVALID_ARGS);
  } else {
    block_count = static_cast<uint32_t>(options.device_block_size * options.device_block_count /
                                        kPageSize / kPagesPerBlock);
  }

  if (zx::result channel = device_watcher::RecursiveWaitForFile(
          "/dev/sys/platform/00:00:2e/nand-ctl", kDeviceWaitTime);
      channel.is_error()) {
    std::cout << "Failed waiting for /dev/sys/platform/00:00:2e/nand-ctl to appear: "
              << channel.status_string() << std::endl;
    return channel.take_error();
  }

  std::optional<ramdevice_client::RamNand> ram_nand;
  fuchsia_hardware_nand::wire::RamNandInfo config = {
      .vmo = std::move(vmo),
      .nand_info =
          {
              .page_size = kPageSize,
              .pages_per_block = kPagesPerBlock,
              .num_blocks = block_count,
              .ecc_bits = 8,
              .oob_size = kOobSize,
              .nand_class = fuchsia_hardware_nand::wire::Class::kFtl,
          },
      .fail_after = options.fail_after,
  };
  if (zx::result status =
          zx::make_result(ramdevice_client::RamNand::Create(std::move(config), &ram_nand));
      status.is_error()) {
    std::cout << "RamNand::Create failed: " << status.status_string() << std::endl;
    return status.take_error();
  }

  std::string ftl_path = std::string(ram_nand->path()) + "/ftl/block";
  if (zx::result channel = device_watcher::RecursiveWaitForFile(ftl_path.c_str(), kDeviceWaitTime);
      channel.is_error()) {
    std::cout << "Failed waiting for " << ftl_path << " to appear: " << channel.status_string()
              << std::endl;
    return channel.take_error();
  }
  return zx::ok(std::make_pair(*std::move(ram_nand), std::move(ftl_path)));
}

}  // namespace

std::string StripTrailingSlash(const std::string& in) {
  if (!in.empty() && in.back() == '/') {
    return in.substr(0, in.length() - 1);
  }
  return in;
}

zx::result<> FsUnbind(const std::string& mount_path) {
  fdio_ns_t* ns;
  if (auto status = zx::make_result(fdio_ns_get_installed(&ns)); status.is_error()) {
    return status;
  }
  if (auto status = zx::make_result(fdio_ns_unbind(ns, StripTrailingSlash(mount_path).c_str()));
      status.is_error()) {
    std::cout << "Unable to unbind: " << status.status_string() << std::endl;
    return status;
  }
  return zx::ok();
}

// Returns device and device path.
zx::result<std::pair<RamDevice, std::string>> CreateRamDevice(
    const TestFilesystemOptions& options) {
  RamDevice ram_device;
  std::string device_path;

  if (options.use_ram_nand) {
    auto ram_nand_or = CreateRamNand(options);
    if (ram_nand_or.is_error()) {
      return ram_nand_or.take_error();
    }
    auto [ram_nand, nand_device_path] = std::move(ram_nand_or).value();
    ram_device = RamDevice(std::move(ram_nand));
    device_path = std::move(nand_device_path);
  } else {
    auto ram_disk_or = CreateRamDisk(options);
    if (ram_disk_or.is_error()) {
      return ram_disk_or.take_error();
    }
    auto [device, ram_disk_path] = std::move(ram_disk_or).value();
    ram_device = RamDevice(std::move(device));
    device_path = std::move(ram_disk_path);
  }

  // Create an FVM partition if requested.
  if (options.use_fvm) {
    storage::FvmOptions fvm_options = {.initial_fvm_slice_count = options.initial_fvm_slice_count};
    auto fvm_partition_or = storage::CreateFvmPartition(
        device_path, static_cast<int>(options.fvm_slice_size), fvm_options);
    if (fvm_partition_or.is_error()) {
      return fvm_partition_or.take_error();
    }

    if (options.dummy_fvm_partition_size > 0) {
      zx::result fvm_device =
          component::Connect<fuchsia_hardware_block_volume::VolumeManager>(device_path + "/fvm");
      if (fvm_device.is_error()) {
        std::cout << "Could not open FVM driver: " << fvm_device.status_string() << std::endl;
        return fvm_device.take_error();
      }

      uint64_t slice_count = options.dummy_fvm_partition_size / options.fvm_slice_size;
      uuid::Uuid type_guid({0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
                            0x01, 0x02, 0x03, 0x04});
      uuid::Uuid instance_guid({0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03,
                                0x04, 0x01, 0x02, 0x03, 0x04});
      std::string_view name = "extra";
      if (zx::result res = fs_management::FvmAllocatePartition(*fvm_device, slice_count, type_guid,
                                                               instance_guid, name, 0);
          res.is_error()) {
        std::cout << "Could not allocate extra FVM partition: " << res.status_string() << std::endl;
        return res.take_error();
      }
    }

    return zx::ok(std::make_pair(std::move(ram_device), std::move(fvm_partition_or).value()));
  }
  return zx::ok(std::make_pair(std::move(ram_device), std::move(device_path)));
}

zx::result<> FsFormat(const std::string& device_path, fs_management::FsComponent& component,
                      const fs_management::MkfsOptions& options, bool create_default_volume) {
  zx::result<> status;
  if (create_default_volume) {
    auto crypt_client = GetCryptService();
    if (crypt_client.is_error())
      return crypt_client.take_error();
    status = fs_management::MkfsWithDefault(device_path.c_str(), component, options,
                                            *std::move(crypt_client));
  } else {
    status = zx::make_result(fs_management::Mkfs(device_path.c_str(), component, options));
  }
  if (status.is_error()) {
    std::cout << "Could not format file system: " << status.status_string() << std::endl;
    return status;
  }
  return zx::ok();
}

zx::result<std::pair<std::unique_ptr<fs_management::SingleVolumeFilesystemInterface>,
                     fs_management::NamespaceBinding>>
FsMount(const std::string& device_path, const std::string& mount_path,
        fs_management::FsComponent& component, const fs_management::MountOptions& options) {
  zx::result device = component::Connect<fuchsia_hardware_block::Block>(device_path);
  if (device.is_error()) {
    std::cout << "Could not open device: " << device_path << ": " << device.status_string()
              << std::endl;
    return device.take_error();
  }

  // Uncomment the following line to force an fsck at the end of every transaction (where
  // supported).
  // options.fsck_after_every_transaction = true;

  auto LogMountError = [](const auto& error) {
    std::cout << "Could not mount file system: " << error.status_string() << std::endl;
  };

  std::unique_ptr<fs_management::SingleVolumeFilesystemInterface> fs;
  if (component.is_multi_volume()) {
    auto result = fs_management::MountMultiVolumeWithDefault(std::move(device.value()), component,
                                                             options, kDefaultVolumeName);
    if (result.is_error()) {
      LogMountError(result);
      return result.take_error();
    }
    fs = std::make_unique<fs_management::StartedSingleVolumeMultiVolumeFilesystem>(
        std::move(*result));
  } else {
    auto result = fs_management::Mount(std::move(device.value()), component, options);
    if (result.is_error()) {
      LogMountError(result);
      return result.take_error();
    }
    fs = std::make_unique<fs_management::StartedSingleVolumeFilesystem>(std::move(*result));
  }
  auto data = fs->DataRoot();
  if (data.is_error()) {
    LogMountError(data);
    return data.take_error();
  }
  auto binding = fs_management::NamespaceBinding::Create(mount_path.c_str(), std::move(*data));
  if (binding.is_error()) {
    LogMountError(binding);
    return binding.take_error();
  }
  return zx::ok(std::make_pair(std::move(fs), std::move(*binding)));
}

// Returns device and device path.
zx::result<std::pair<RamDevice, std::string>> OpenRamDevice(const TestFilesystemOptions& options) {
  if (!options.vmo->is_valid()) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  RamDevice ram_device;
  std::string device_path;

  if (options.use_ram_nand) {
    // First create the ram-nand device.
    auto ram_nand_or = CreateRamNand(options);
    if (ram_nand_or.is_error()) {
      return ram_nand_or.take_error();
    }
    auto [ram_nand, ftl_device_path] = std::move(ram_nand_or).value();
    ram_device = RamDevice(std::move(ram_nand));
    device_path = std::move(ftl_device_path);
  } else {
    auto ram_disk_or = CreateRamDisk(options);
    if (ram_disk_or.is_error()) {
      std::cout << "Unable to create ram-disk" << std::endl;
    }

    auto [device, ram_disk_path] = std::move(ram_disk_or).value();
    ram_device = RamDevice(std::move(device));
    device_path = std::move(ram_disk_path);
  }

  if (options.use_fvm) {
    // Now bind FVM to it.
    std::string controller_path = device_path + "/device_controller";
    zx::result controller = component::Connect<fuchsia_device::Controller>(controller_path);
    if (controller.is_error()) {
      return controller.take_error();
    }
    auto status = storage::BindFvm(controller.value());
    if (status.is_error()) {
      std::cout << "Unable to bind FVM: " << status.status_string() << std::endl;
      return status.take_error();
    }

    device_path.append("/fvm/fs-test-partition-p-1/block");
  }

  if (zx::result channel =
          device_watcher::RecursiveWaitForFile(device_path.c_str(), kDeviceWaitTime);
      channel.is_error()) {
    std::cout << "Failed waiting for " << device_path << " to appear: " << channel.status_string()
              << std::endl;
    return channel.take_error();
  }

  return zx::ok(std::make_pair(std::move(ram_device), std::move(device_path)));
}

TestFilesystemOptions TestFilesystemOptions::DefaultBlobfs() {
  return TestFilesystemOptions{.description = "Blobfs",
                               .use_fvm = true,
                               .device_block_size = 512,
                               .device_block_count = 196'608,
                               .fvm_slice_size = 32'768,
                               .num_inodes = 512,  // blobfs can grow as needed.
                               .filesystem = &BlobfsFilesystem::SharedInstance()};
}

TestFilesystemOptions TestFilesystemOptions::BlobfsWithoutFvm() {
  TestFilesystemOptions blobfs_with_no_fvm = TestFilesystemOptions::DefaultBlobfs();
  blobfs_with_no_fvm.description = "BlobfsWithoutFvm";
  blobfs_with_no_fvm.use_fvm = false;
  blobfs_with_no_fvm.num_inodes = 2048;
  return blobfs_with_no_fvm;
}

std::ostream& operator<<(std::ostream& out, const TestFilesystemOptions& options) {
  return out << options.description;
}

std::vector<TestFilesystemOptions> AllTestFilesystems() {
  static const std::vector<TestFilesystemOptions>* options = [] {
    const char kConfigFile[] = "/pkg/config/config.json";
    json_parser::JSONParser parser;
    auto config = parser.ParseFromFile(std::string(kConfigFile));
    auto iter = config.FindMember("library");
    std::unique_ptr<Filesystem> filesystem;
    if (iter != config.MemberEnd()) {
      void* handle = dlopen(iter->value.GetString(), RTLD_NOW);
      FX_CHECK(handle) << dlerror();
      auto get_filesystem =
          reinterpret_cast<std::unique_ptr<Filesystem> (*)()>(dlsym(handle, "_Z13GetFilesystemv"));
      FX_CHECK(get_filesystem) << dlerror();
      filesystem = get_filesystem();
    } else {
      filesystem = JsonFilesystem::NewFilesystem(config).value();
    }
    std::string name = config["name"].GetString();
    auto options = new std::vector<TestFilesystemOptions>;
    iter = config.FindMember("options");
    if (iter == config.MemberEnd()) {
      name[0] = static_cast<char>(toupper(name[0]));
      options->push_back(TestFilesystemOptions{.description = name,
                                               .use_fvm = false,
                                               .device_block_size = 512,
                                               .device_block_count = 196'608,
                                               .filesystem = filesystem.get()});
    } else {
      for (rapidjson::SizeType i = 0; i < iter->value.Size(); ++i) {
        const auto& opt = iter->value[i];
        options->push_back(TestFilesystemOptions{
            .description = opt["description"].GetString(),
            .use_fvm = opt["use_fvm"].GetBool(),
            .has_min_volume_size = ConfigGetOrDefault<bool>(opt, "has_min_volume_size", false),
            .device_block_size = ConfigGetOrDefault<uint64_t>(opt, "device_block_size", 512),
            .device_block_count = ConfigGetOrDefault<uint64_t>(opt, "device_block_count", 196'608),
            .fvm_slice_size = 32'768,
            .filesystem = filesystem.get(),
        });
      }
    }
    [[maybe_unused]] Filesystem* fs = filesystem.release();  // Deliberate leak
    return options;
  }();

  return *options;
}

TestFilesystemOptions OptionsWithDescription(std::string_view description) {
  for (const auto& options : AllTestFilesystems()) {
    if (options.description == description) {
      return options;
    }
  }
  FX_LOGS(FATAL) << "No test options with description: " << description;
  abort();
}

std::vector<TestFilesystemOptions> MapAndFilterAllTestFilesystems(
    const std::function<std::optional<TestFilesystemOptions>(const TestFilesystemOptions&)>&
        map_and_filter) {
  std::vector<TestFilesystemOptions> results;
  for (const TestFilesystemOptions& options : AllTestFilesystems()) {
    auto r = map_and_filter(options);
    if (r) {
      results.push_back(*std::move(r));
    }
  }
  return results;
}

// -- FilesystemInstance --

// Default implementation
zx::result<> FilesystemInstance::Unmount(const std::string& mount_path) {
  // Detach from the namespace.
  if (auto status = FsUnbind(mount_path); status.is_error()) {
    std::cerr << "FsUnbind failed: " << status.status_string() << std::endl;
    return status;
  }

  auto filesystem = fs();
  if (!filesystem) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }
  auto status = filesystem->Unmount();
  if (status.is_error()) {
    std::cerr << "Shut down failed: " << status.status_string() << std::endl;
    return status;
  }
  return zx::ok();
}

// -- Blobfs --

class BlobfsInstance : public FilesystemInstance {
 public:
  BlobfsInstance(RamDevice device, std::string device_path)
      : device_(std::move(device)),
        component_(fs_management::FsComponent::FromDiskFormat(fs_management::kDiskFormatBlobfs)),
        device_path_(std::move(device_path)) {}

  zx::result<> Format(const TestFilesystemOptions& options) override {
    fs_management::MkfsOptions mkfs_options;
    mkfs_options.deprecated_padded_blobfs_format =
        options.blob_layout_format == blobfs::BlobLayoutFormat::kDeprecatedPaddedMerkleTreeAtStart;
    mkfs_options.num_inodes = options.num_inodes;
    return FsFormat(device_path_, component_, mkfs_options,
                    /*create_default_volume=*/false);
  }

  zx::result<> Mount(const std::string& mount_path,
                     const fs_management::MountOptions& options) override {
    auto res = FsMount(device_path_, mount_path, component_, options);
    if (res.is_error()) {
      // We can't reuse the component in the face of errors.
      component_ = fs_management::FsComponent::FromDiskFormat(fs_management::kDiskFormatBlobfs);
      return res.take_error();
    }
    fs_ = std::move(res->first);
    binding_ = std::move(res->second);
    return zx::ok();
  }

  zx::result<> Unmount(const std::string& mount_path) override {
    zx::result result = FilesystemInstance::Unmount(mount_path);
    // After unmounting, the component cannot be used again, so set up a new component.
    component_ = fs_management::FsComponent::FromDiskFormat(fs_management::kDiskFormatBlobfs);
    return result;
  }

  zx::result<> Fsck() override {
    fs_management::FsckOptions options{
        .verbose = false,
        .never_modify = true,
        .always_modify = false,
        .force = true,
    };
    return zx::make_result(fs_management::Fsck(device_path_, component_, options));
  }

  zx::result<std::string> DevicePath() const override { return zx::ok(std::string(device_path_)); }
  storage::RamDisk* GetRamDisk() override { return std::get_if<storage::RamDisk>(&device_); }
  ramdevice_client::RamNand* GetRamNand() override {
    return std::get_if<ramdevice_client::RamNand>(&device_);
  }
  fs_management::SingleVolumeFilesystemInterface* fs() override { return fs_.get(); }
  fidl::UnownedClientEnd<fuchsia_io::Directory> ServiceDirectory() const override {
    return fs_->ExportRoot();
  }
  void Reset() override {
    binding_.Reset();
    fs_.reset();
  }

  std::string GetMoniker() const override {
    return component_.collection_name().has_value()
               ? *component_.collection_name() + ":" + component_.child_name()
               : component_.child_name();
  }

 private:
  RamDevice device_;
  fs_management::FsComponent component_;
  std::string device_path_;
  std::unique_ptr<fs_management::SingleVolumeFilesystemInterface> fs_;
  fs_management::NamespaceBinding binding_;
};

std::unique_ptr<FilesystemInstance> BlobfsFilesystem::Create(RamDevice device,
                                                             std::string device_path) const {
  return std::make_unique<BlobfsInstance>(std::move(device), std::move(device_path));
}

zx::result<std::unique_ptr<FilesystemInstance>> BlobfsFilesystem::Open(
    const TestFilesystemOptions& options) const {
  auto result = OpenRamDevice(options);
  if (result.is_error()) {
    return result.take_error();
  }
  auto [ram_nand, device_path] = std::move(result).value();
  return zx::ok(std::make_unique<BlobfsInstance>(std::move(ram_nand), std::move(device_path)));
}

}  // namespace fs_test
