// Copyright 2021 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 <lib/fdio/fd.h>
#include <lib/zx/channel.h>
#include <lib/zx/status.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/errors.h>

#include <cstdint>
#include <iostream>
#include <map>
#include <memory>
#include <optional>
#include <utility>

#include <fbl/unique_fd.h>
#include <safemath/checked_math.h>

#include "lib/async/dispatcher.h"
#include "src/lib/storage/block_client/cpp/remote_block_device.h"
#include "src/storage/blobfs/blobfs.h"
#include "src/storage/blobfs/format.h"
#include "src/storage/extractor/c/extractor.h"
#include "src/storage/extractor/cpp/extractor.h"

namespace extractor {
namespace {

// Walks the file system and collects interesting metadata.
class FsWalker {
 public:
  ~FsWalker() {
    if (vfs_)
      vfs_->TearDown();
  }

  static zx::status<std::unique_ptr<FsWalker>> Create(fbl::unique_fd input_fd,
                                                      Extractor& extractor);

  zx::status<> Walk(async_dispatcher_t* dispatcher);

 private:
  // Returns maximum addressable block in the fs.
  uint64_t BlockLimit() const { return blobfs::DataStartBlock(info_) + blobfs::DataBlocks(Info()); }

  // Returns maximum addressable byte in the fs.
  uint64_t ByteLimit() const { return BlockLimit() * Info().block_size; }

  // Walks the partition and marks all bytes as reported by ByteLimit() as unused for non-fvm
  // partition or unmapped for fvm partition.
  zx::status<> WalkPartition() const;

  // Walks different segments, like inode table and bitmaps except data segment, of the filesystem.
  // Marks them as data unmodified.
  zx::status<> WalkSegments() const;

  // LoadAndVerify each blob and dump the corrupted files.
  zx::status<> WalkBlobs(blobfs::Blobfs& blobfs) const;

  // Dumps each block in an extent
  zx::status<> ExtentBlockHandler(blobfs::Extent extent) const;

  // Iterates through all the extents of an inode, node_num is inode index,
  // alloc_block is a counter for number of blocks traversed.
  zx::status<> WalkExtentContainer(blobfs::Blobfs& blobfs, uint32_t node_num, uint32_t alloc_block,
                                   blobfs::Inode ino) const;

  zx::status<std::unique_ptr<blobfs::Blobfs>> CreateBlobfs(async_dispatcher_t* dispatcher);

  const blobfs::Superblock& Info() const { return info_; }

  FsWalker(fbl::unique_fd input_fd, Extractor& extractor);

  // Not copyable or movable
  FsWalker(const FsWalker&) = delete;
  FsWalker& operator=(const FsWalker&) = delete;
  FsWalker(FsWalker&&) = delete;
  FsWalker& operator=(FsWalker&&) = delete;

  // Loads superblock located at start_offset. If the copy of superblock has valid
  // magic values, the function returns zx::ok().
  zx::status<> TryLoadSuperblock(uint64_t start_offset);

  // Loads one valid copy of superblock from the input_fd_.
  // Primary superblock location is given highest priority followed by backup superblock
  // of fvm partition and then non-fvm partition.
  zx::status<> LoadSuperblock();

  // The valid copy of superblock.
  blobfs::Superblock info_;

  // Pointer to extractor.
  Extractor& extractor_;

  // File from where the filesystem is parsed/loaded.
  fbl::unique_fd input_fd_;

  // Pointer to vfs.
  std::unique_ptr<fs::PagedVfs> vfs_;
};

blobfs::MountOptions ReadOnlyOptions() {
  return blobfs::MountOptions{.writability = blobfs::Writability::ReadOnlyDisk};
}

zx::status<std::unique_ptr<blobfs::Blobfs>> FsWalker::CreateBlobfs(async_dispatcher_t* dispatcher) {
  zx::channel root_client;
  if (zx_status_t status = fdio_fd_clone(input_fd_.get(), root_client.reset_and_get_address());
      status != ZX_OK) {
    std::cerr << "Error transferring input fd to channel" << std::endl;
    std::cerr << "Status: " << status << std::endl;
    return zx::error(status);
  }

  std::unique_ptr<block_client::RemoteBlockDevice> device;
  if (zx_status_t status =
          block_client::RemoteBlockDevice::Create(std::move(root_client), &device) != ZX_OK) {
    std::cerr << "Error creating Remote Block Device";
    std::cerr << "Status: " << status << std::endl;
    return zx::error(status);
  }

  vfs_ = std::make_unique<fs::PagedVfs>(dispatcher);
  if (auto status = vfs_->Init(); status.is_error())
    return zx::error(status.error_value());

  auto blobfs_or =
      blobfs::Blobfs::Create(dispatcher, std::move(device), vfs_.get(), ReadOnlyOptions());
  if (blobfs_or.is_error()) {
    std::cerr << "Cannot create filesystem for checking: " << blobfs_or.status_string();
    return zx::error(blobfs_or.status_value());
  }
  return zx::ok(std::move(blobfs_or.value()));
}

FsWalker::FsWalker(fbl::unique_fd input_fd, Extractor& extractor)
    : extractor_(extractor), input_fd_(std::move(input_fd)) {}

zx::status<std::unique_ptr<FsWalker>> FsWalker::Create(fbl::unique_fd input_fd,
                                                       Extractor& extractor) {
  auto walker = std::unique_ptr<FsWalker>(new FsWalker(std::move(input_fd), extractor));

  if (auto status = walker->LoadSuperblock(); status.is_error()) {
    std::cerr << "Loading superblock failed" << std::endl;
    return zx::error(status.error_value());
  }

  return zx::ok(std::move(walker));
}

zx::status<> FsWalker::Walk(async_dispatcher_t* dispatcher) {
  if (auto status = WalkPartition(); status.is_error()) {
    std::cerr << "Walking partition failed" << std::endl;
    return status;
  }

  if (auto status = WalkSegments(); status.is_error()) {
    std::cerr << "Walking segments failed" << std::endl;
    return status;
  }

  auto blob_or = CreateBlobfs(dispatcher);
  if (blob_or.is_error()) {
    std::cerr << "Creating Blobfs instance failed" << std::endl;
    return zx::error(blob_or.error_value());
  }
  return WalkBlobs(*blob_or.value());
}

zx::status<> FsWalker::WalkBlobs(blobfs::Blobfs& blobfs) const {
  for (unsigned n = 0; n < blobfs.Info().inode_count; n++) {
    auto inode_or = blobfs.GetNode(n);
    blobfs::Inode ino = *inode_or.value();
    blobfs::NodePrelude header = ino.header;
    if (header.IsAllocated() && header.IsInode()) {
      uint32_t alloc_block = 0;
      if (auto status = blobfs.LoadAndVerifyBlob(n) != ZX_OK) {
        if (auto status = ExtentBlockHandler(ino.extents[0]); status.is_error()) {
          return status;
        }
        alloc_block += ino.extents[0].Length();
        if (alloc_block < ino.block_count && header.next_node != 0) {
          return WalkExtentContainer(blobfs, header.next_node, alloc_block, ino);
        }
      }
    }
  }
  return zx::ok();
}

zx::status<> FsWalker::WalkExtentContainer(blobfs::Blobfs& blobfs, uint32_t node_num,
                                           uint32_t alloc_block, blobfs::Inode ino) const {
  auto inode_or = blobfs.GetNode(node_num);
  if (inode_or.is_error()) {
    return zx::error(inode_or.error_value());
  }
  blobfs::Inode inode = *inode_or.value();
  blobfs::ExtentContainer* node = inode.AsExtentContainer();
  blobfs::NodePrelude header = node->header;
  for (int i = 0; i < node->extent_count; i++) {
    if (auto status = ExtentBlockHandler(node->extents[i]); status.is_error()) {
      return status;
    }
    alloc_block += node->extents[i].Length();
  }
  if (alloc_block < ino.block_count && header.next_node != 0) {
    return WalkExtentContainer(blobfs, header.next_node, alloc_block, ino);
  }
  return zx::ok();
}

zx::status<> FsWalker::ExtentBlockHandler(blobfs::Extent extent) const {
  ExtentProperties properties = {.extent_kind = ExtentKind::Data,
                                 .data_kind = DataKind::Unmodified};

  if (auto status = extractor_.AddBlocks(extent.Start() + blobfs::DataStartBlock(info_),
                                         extent.Length(), properties);
      status.is_error()) {
    std::cerr << "FAIL: Dump corrupt blob" << std::endl;
    return status;
  }
  return zx::ok();
}

zx::status<> FsWalker::WalkPartition() const {
  auto max_offset = ByteLimit();
  ExtentProperties properties;
  if (!(info_.flags & blobfs::kBlobFlagFVM)) {
    // If this is a non-fvm fs, mark all blocks as unused. Other walkers will override it
    // later. Tnere are no unmapped blocks in non-fvm partition.
    properties.extent_kind = ExtentKind::Unused;
  } else {
    // If this is a fvm fs, mark all blocks as unmapped. Other walkers will override it
    // later. Tnere are no unmapped blocks in non-fvm partition.
    properties.extent_kind = ExtentKind::Unmmapped;
  }
  properties.data_kind = DataKind::Skipped;
  return extractor_.Add(0, max_offset, properties);
}

zx::status<> FsWalker::WalkSegments() const {
  ExtentProperties properties{.extent_kind = ExtentKind::Data, .data_kind = DataKind::Unmodified};
  if (auto status = extractor_.AddBlocks(blobfs::kSuperblockOffset, blobfs::kBlobfsSuperblockBlocks,
                                         properties);
      status.is_error()) {
    std::cerr << "FAIL: Add superblock" << std::endl;
    return status;
  }
  if (info_.flags & blobfs::kBlobFlagFVM) {
    if (auto status = extractor_.AddBlocks(blobfs::kFVMBackupSuperblockOffset,
                                           blobfs::kBlobfsSuperblockBlocks, properties);
        status.is_error()) {
      std::cerr << "FAIL: Add backup superblock" << std::endl;
      return status;
    }
  }
  if (auto status = extractor_.AddBlocks(blobfs::BlockMapStartBlock(info_),
                                         blobfs::BlockMapBlocks(info_), properties);
      status.is_error()) {
    std::cerr << "FAIL: Add blockmap" << std::endl;
    return status;
  }
  if (auto status = extractor_.AddBlocks(blobfs::NodeMapStartBlock(info_),
                                         blobfs::NodeMapBlocks(info_), properties);
      status.is_error()) {
    std::cerr << "FAIL: Add nodemap" << std::endl;
    return status;
  }
  if (auto status = extractor_.AddBlocks(blobfs::JournalStartBlock(info_),
                                         blobfs::JournalBlocks(info_), properties);
      status.is_error()) {
    std::cerr << "FAIL: Add journal" << std::endl;
    return status;
  }
  return zx::ok();
}

zx::status<> FsWalker::TryLoadSuperblock(uint64_t start_offset) {
  off_t pread_offset;
  if (!safemath::MakeCheckedNum<uint64_t>(start_offset)
           .Cast<off_t>()
           .AssignIfValid(&pread_offset)) {
    return zx::error(ZX_ERR_OUT_OF_RANGE);
  }

  if (pread(input_fd_.get(), &info_, sizeof(info_), pread_offset) != sizeof(info_)) {
    return zx::error(ZX_ERR_IO);
  }

  // Does info_ look like superblock?
  if (info_.magic0 == blobfs::kBlobfsMagic0 && info_.magic1 == blobfs::kBlobfsMagic1) {
    return zx::ok();
  }
  return zx::error(ZX_ERR_BAD_STATE);
}

zx::status<> FsWalker::LoadSuperblock() {
  ExtentProperties properties{.extent_kind = ExtentKind::Data, .data_kind = DataKind::Unmodified};
  auto load_status = TryLoadSuperblock(blobfs::kSuperblockOffset * blobfs::kBlobfsBlockSize);
  if (load_status.is_ok()) {
    return load_status;
  }
  // If we fail to load primary superblock, dump primary superblock
  if (auto status = extractor_.AddBlocks(blobfs::kSuperblockOffset, 1, properties);
      status.is_error()) {
    std::cerr << "FAIL: Add primary superblock" << std::endl;
    return status;
  }
  return load_status;
}

}  // namespace

zx::status<> BlobfsExtract(fbl::unique_fd input_fd, Extractor& extractor) {
  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  if (zx_status_t status = loop.StartThread(); status != ZX_OK) {
    std::cerr << "Cannot initialize dispatch loop: " << zx_status_get_string(status);
    return zx::error(status);
  }

  auto walker_or = FsWalker::Create(std::move(input_fd), extractor);
  if (walker_or.is_error()) {
    std::cerr << "Walker: Init failure: " << walker_or.error_value() << std::endl;
    return zx::error(walker_or.error_value());
  }
  std::unique_ptr<FsWalker> walker = std::move(walker_or.value());
  return walker->Walk(loop.dispatcher());
}

}  // namespace extractor
