// 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 <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 "src/storage/extractor/c/extractor.h"
#include "src/storage/extractor/cpp/extractor.h"
#include "src/storage/minfs/format.h"
#include "src/storage/minfs/fsck.h"

namespace extractor {
namespace {

// Returns true if type of block belonging to an inode may contain pii.
bool IsPii(const minfs::Inode& inode, minfs::BlockType type) {
  return inode.magic == minfs::kMinfsMagicFile && type == minfs::BlockType::kDirect;
}

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

 private:
  zx::status<> ReadBlock(uint64_t block_number, uint8_t* buf) const {
    if (pread(input_fd_.get(), buf, Info().block_size, block_number * Info().block_size) !=
        Info().block_size) {
      return zx::error(ZX_ERR_IO);
    }
    return zx::ok();
  }

  // Returns true if the block_number is in addressable range. For non-fvm based partition, it means
  // the block number is less than the partition size. For fvm based partition, this means the
  // block_number is within some allocated/mapped slice range.
  bool IsMapped(uint32_t block_number) const;

  // All the block numbers stored in double indirect and indirect blocks are relative to
  // Superblock.DataStartBlock(). This helper routine converts such block numbers to absolute block
  // number.
  zx::status<uint32_t> DataBlockToAbsoluteBlock(uint32_t n) const {
    auto blk_or = safemath::CheckAdd(n, static_cast<uint32_t>(Info().DataStartBlock()));
    if (blk_or.IsValid()) {
      return zx::ok(blk_or.ValueOrDie());
    }
    return zx::error(ZX_ERR_OUT_OF_RANGE);
  }

  // Given a block that belongs to a file/directory, this function adds the block to extractor with
  // right set of properties.
  zx::status<> InodeBlockHandler(uint32_t block_number, bool pii) const;

  // Walks indirect and double indirect block at block_number.
  zx::status<> WalkXkIndirects(const minfs::Inode& inode, minfs::ino_t ino, uint32_t block_number,
                               bool is_double_indirect) const;

  // Returns reference to inode for given inode number
  const minfs::Inode& GetInode(minfs::ino_t inode_number) const {
    ZX_ASSERT(inode_number < Info().inode_count);
    return inode_table_[inode_number];
  }

  // Walks all in-use inode and calls handler on those.
  // "in-use" here means the file is marked as allocated in inode bitmap table.
  zx::status<> WalkInodes() const;

  // Returns maximum addressable block in the fs.
  uint64_t BlockLimit() const { return Info().DataStartBlock() + 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;

  // Returns a reference to loaded superblock.
  const minfs::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();

  // Loads entire contents of inode table in memory.
  zx::status<> LoadInodeTable();

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

  // Pointer to extractor.
  Extractor& extractor_;

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

  // In-memory copy of inode table.
  std::unique_ptr<minfs::Inode[]> inode_table_;
};

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\n";
    return zx::error(status.error_value());
  }
  if (auto status = walker->LoadInodeTable(); status.is_error()) {
    return zx::error(status.error_value());
  }
  return zx::ok(std::move(walker));
}

zx::status<> FsWalker::Walk() const {
  if (auto status = WalkPartition(); status.is_error()) {
    return status;
  }

  if (auto status = WalkSegments(); status.is_error()) {
    return status;
  }

  return WalkInodes();
}

bool FsWalker::IsMapped(uint32_t block_number) const {
  auto info = Info();
  if (block_number > BlockLimit()) {
    return false;
  }

  if (block_number == minfs::kSuperblockStart || block_number == info.BackupSuperblockStart()) {
    return true;
  }
  if (block_number >= info.InodeBitmapStartBlock() &&
      block_number < (info.InodeBitmapStartBlock() + minfs::InodeBitmapBlocks(Info()))) {
    return true;
  }
  if (block_number >= info.DataBitmapStartBlock() &&
      block_number < (info.DataBitmapStartBlock() + minfs::BlockBitmapBlocks(Info()))) {
    return true;
  }
  if (block_number >= info.InodeTableStartBlock() &&
      block_number < (info.InodeTableStartBlock() + minfs::InodeBlocks(Info()))) {
    return true;
  }
  if (block_number >= minfs::JournalStartBlock(info) &&
      block_number < (minfs::JournalStartBlock(info) + minfs::JournalBlocks(Info()))) {
    return true;
  }
  if (block_number >= info.DataStartBlock() &&
      block_number < (info.DataStartBlock() + minfs::DataBlocks(Info()))) {
    return true;
  }
  return false;
}

zx::status<> FsWalker::InodeBlockHandler(uint32_t block_number, bool pii) const {
  ExtentProperties properties = {.extent_kind = ExtentKind::Data,
                                 .data_kind = DataKind::Unmodified};

  ZX_ASSERT(block_number > Info().DataStartBlock());

  if (pii) {
    properties.extent_kind = ExtentKind::Pii;
  }

  if (!IsMapped(block_number)) {
    properties.data_kind = DataKind::Skipped;
  }

  return extractor_.AddBlock(block_number, properties);
}

zx::status<> FsWalker::WalkXkIndirects(const minfs::Inode& inode, minfs::ino_t ino,
                                       uint32_t block_number, bool is_double_indirect) const {
  ZX_ASSERT(block_number >= Info().DataStartBlock());
  if (block_number == Info().DataStartBlock()) {
    return zx::ok();
  }

  if (auto status = InodeBlockHandler(block_number, IsPii(inode, minfs::BlockType::kIndirect));
      status.is_error()) {
    return status;
  }

  // If this block is not mapped then we are done here.
  if (!IsMapped(block_number)) {
    return zx::ok();
  }

  uint8_t data[Info().BlockSize()];
  if (auto status = ReadBlock(block_number, data); status.is_error()) {
    return status;
  }
  uint32_t* entry = reinterpret_cast<uint32_t*>(data);
  for (unsigned i = 0; i < minfs::kMinfsDirectPerIndirect; i++) {
    if (entry[i] == 0) {
      continue;
    }
    auto absolute_block_number_or = DataBlockToAbsoluteBlock(entry[i]);
    if (absolute_block_number_or.is_error()) {
      continue;
    }
    if (!is_double_indirect) {
      if (auto status = InodeBlockHandler(absolute_block_number_or.value(),
                                          IsPii(inode, minfs::BlockType::kDirect));
          status.is_error()) {
        return status;
      }
    } else {
      if (auto status = WalkXkIndirects(inode, ino, absolute_block_number_or.value(), false);
          status.is_error()) {
        return status;
      }
    }
  }
  return zx::ok();
}

zx::status<> FsWalker::WalkInodes() const {
  for (minfs::ino_t ino = 0; ino < Info().inode_count; ino++) {
    auto inode = GetInode(ino);
    if (inode.magic != minfs::kMinfsMagicFile && inode.magic != minfs::kMinfsMagicDir) {
      continue;
    }

    for (uint32_t n : inode.dnum) {
      if (n == 0) {
        continue;
      }
      auto absolute_block_number_or = DataBlockToAbsoluteBlock(n);
      if (absolute_block_number_or.is_error()) {
        continue;
      }
      if (auto status = InodeBlockHandler(absolute_block_number_or.value(),
                                          IsPii(inode, minfs::BlockType::kDirect));
          status.is_error()) {
        return status;
      }
    }

    // Walk indirect blocks.
    for (unsigned int n : inode.inum) {
      auto absolute_block_number_or = DataBlockToAbsoluteBlock(n);
      if (absolute_block_number_or.is_error()) {
        continue;
      }
      if (auto status = WalkXkIndirects(inode, ino, absolute_block_number_or.value(), false);
          status.is_error()) {
        return status;
      }
    }

    // Walk double indirect blocks.
    for (unsigned int n : inode.dinum) {
      auto absolute_block_number_or = DataBlockToAbsoluteBlock(n);
      if (absolute_block_number_or.is_error()) {
        continue;
      }
      if (auto status = WalkXkIndirects(inode, ino, absolute_block_number_or.value(), true);
          status.is_error()) {
        return status;
      }
    }
  }
  return zx::ok();
}

zx::status<> FsWalker::WalkPartition() const {
  auto max_offset = ByteLimit();
  ExtentProperties properties;
  if (!Info().GetFlagFvm()) {
    // 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 {
  auto info = Info();

  ExtentProperties properties{.extent_kind = ExtentKind::Data, .data_kind = DataKind::Unmodified};

  if (auto status =
          extractor_.AddBlocks(minfs::kSuperblockStart, minfs::kSuperblockBlocks, properties);
      status.is_error()) {
    return status;
  }
  if (auto status =
          extractor_.AddBlocks(info.BackupSuperblockStart(), minfs::kSuperblockBlocks, properties);
      status.is_error()) {
    return status;
  }
  if (auto status =
          extractor_.AddBlocks(info.InodeBitmapStartBlock(), InodeBitmapBlocks(info), properties);
      status.is_error()) {
    return status;
  }
  if (auto status =
          extractor_.AddBlocks(info.DataBitmapStartBlock(), BlockBitmapBlocks(info), properties);
      status.is_error()) {
    return status;
  }
  if (auto status =
          extractor_.AddBlocks(info.InodeTableStartBlock(), InodeBlocks(info), properties);
      status.is_error()) {
    return status;
  }
  if (auto status =
          extractor_.AddBlocks(minfs::JournalStartBlock(info), JournalBlocks(info), properties);
      status.is_error()) {
    return status;
  }

  // Mark all data blocks as unused/skipped.
  properties.extent_kind = ExtentKind::Unused;
  properties.data_kind = DataKind::Skipped;
  return extractor_.AddBlocks(info_.DataStartBlock(), DataBlocks(info), properties);
}

zx::status<> FsWalker::TryLoadSuperblock(uint64_t start_offset) {
  if (pread(input_fd_.get(), &info_, sizeof(info_), start_offset) != sizeof(info_)) {
    return zx::error(ZX_ERR_IO);
  }

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

zx::status<> FsWalker::LoadSuperblock() {
  if (auto status = TryLoadSuperblock(minfs::kSuperblockStart * minfs::kMinfsBlockSize);
      status.is_ok()) {
    return status;
  }
  if (auto status = TryLoadSuperblock(minfs::kFvmSuperblockBackup * minfs::kMinfsBlockSize);
      status.is_ok()) {
    std::cerr << "Found fvm backup superblock valid\n";
    return status;
  }

  auto status = TryLoadSuperblock(minfs::kNonFvmSuperblockBackup * minfs::kMinfsBlockSize);
  if (status.is_ok()) {
    std::cerr << "Found non-fvm backup superblock valid\n";
  }
  return status;
}

zx::status<> FsWalker::LoadInodeTable() {
  inode_table_ =
      std::make_unique<minfs::Inode[]>(InodeBlocks(Info()) * minfs::kMinfsInodesPerBlock);
  ssize_t size = InodeBlocks(Info()) * Info().BlockSize();
  if (pread(input_fd_.get(), inode_table_.get(), size,
            info_.InodeTableStartBlock() * Info().BlockSize()) != size) {
    return zx::error(ZX_ERR_IO);
  }
  return zx::ok();
}

}  // namespace

zx::status<> MinfsExtract(fbl::unique_fd input_fd, Extractor& extractor) {
  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();
}

}  // namespace extractor
