// 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 <fcntl.h>
#include <lib/fdio/spawn.h>
#include <lib/zx/process.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <zircon/device/block.h>

#include <algorithm>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <iterator>
#include <memory>
#include <string>

#include <fbl/unique_fd.h>

#include "src/storage/blobfs/common.h"
#include "src/storage/blobfs/format.h"
#include "src/storage/blobfs/test/blob_utils.h"
#include "src/storage/blobfs/test/integration/blobfs_fixtures.h"
#include "src/storage/extractor/c/extractor.h"
#include "src/storage/extractor/cpp/extractor.h"
#include "src/storage/fs_test/blobfs_test.h"
#include "src/storage/fs_test/fs_test.h"
#include "src/storage/fs_test/fs_test_fixture.h"

namespace extractor {
namespace {

using BlobfsExtractionTest = fs_test::FilesystemTest;

constexpr uint64_t kExtractedImageBlockCount = 2;
constexpr uint64_t kExtractedImageStartOffset = 0;

constexpr uint64_t SuperblockOffset() {
  return kExtractedImageStartOffset + kExtractedImageBlockCount * blobfs::kBlobfsBlockSize;
}

constexpr uint64_t BlockBitmapOffset(const blobfs::Superblock& info) {
  uint64_t block_map_offset =
      SuperblockOffset() + blobfs::kBlobfsSuperblockBlocks * blobfs::kBlobfsBlockSize;
  if (info.flags & blobfs::kBlobFlagFVM) {
    block_map_offset += (blobfs::kBlobfsSuperblockBlocks * blobfs::kBlobfsBlockSize);
  }
  return block_map_offset;
}

constexpr uint64_t NodemapOffset(const blobfs::Superblock& info) {
  return BlockBitmapOffset(info) + blobfs::BlockMapBlocks(info) * blobfs::kBlobfsBlockSize;
}

constexpr uint64_t JournalOffset(const blobfs::Superblock& info) {
  return NodemapOffset(info) + blobfs::NodeMapBlocks(info) * blobfs::kBlobfsBlockSize;
}

constexpr uint64_t DatablockOffset(const blobfs::Superblock& info) {
  return JournalOffset(info) + blobfs::JournalBlocks(info) * blobfs::kBlobfsBlockSize;
}

void CreateInputAndOutputStream(fs_test::TestFilesystem& fs, fbl::unique_fd& input,
                                fbl::unique_fd& output, std::unique_ptr<blobfs::BlobInfo>* blob) {
  std::unique_ptr<blobfs::BlobInfo> blob_info =
      blobfs::GenerateBlob(blobfs::RandomFill, fs.mount_path(), 1 << 17);
  fbl::unique_fd fd;
  ASSERT_NO_FATAL_FAILURE(MakeBlob(*blob_info, &fd));
  ASSERT_EQ(close(fd.release()), 0);
  ASSERT_EQ(fs.Unmount().status_value(), ZX_OK);
  input.reset(open(fs.DevicePath().value().c_str(), O_RDWR));
  ASSERT_TRUE(input);
  char out_path[] = "/tmp/blobfs-extraction.XXXXXX";
  output.reset(mkostemp(out_path, O_RDWR | O_CREAT | O_EXCL));
  ASSERT_TRUE(output);
  if (blob != nullptr) {
    *blob = std::move(blob_info);
  }
}

void Extract(const fbl::unique_fd& input_fd, const fbl::unique_fd& output_fd,
             bool corruptSuperblock) {
  ExtractorOptions options = ExtractorOptions{.force_dump_pii = false,
                                              .add_checksum = false,
                                              .alignment = blobfs::kBlobfsBlockSize,
                                              .compress = false};
  auto extractor_status = Extractor::Create(input_fd.duplicate(), options, output_fd.duplicate());
  ASSERT_EQ(extractor_status.status_value(), ZX_OK);
  auto extractor = std::move(extractor_status.value());
  auto status = BlobfsExtract(input_fd.duplicate(), *extractor);
  if (!corruptSuperblock) {
    ASSERT_TRUE(status.is_ok());
  }
  ASSERT_TRUE(extractor->Write().is_ok());
}

void VerifyInputSuperblock(blobfs::Superblock* info, const fbl::unique_fd& input_fd) {
  ASSERT_EQ(ssize_t{blobfs::kBlobfsBlockSize},
            pread(input_fd.get(), info, blobfs::kBlobfsBlockSize, blobfs::kSuperblockOffset));
  ASSERT_EQ(info->magic0, blobfs::kBlobfsMagic0);
  ASSERT_EQ(info->magic1, blobfs::kBlobfsMagic1);
}

void VerifyOutputSuperblock(blobfs::Superblock* info, const fbl::unique_fd& output_fd) {
  ssize_t superblock_offset = SuperblockOffset();

  char read_buffer[blobfs::kBlobfsBlockSize];
  ASSERT_EQ(pread(output_fd.get(), read_buffer, sizeof(read_buffer), superblock_offset),
            static_cast<ssize_t>(sizeof(read_buffer)));
  ASSERT_EQ(memcmp(info, read_buffer, sizeof(read_buffer)), 0);
}

TEST_P(BlobfsExtractionTest, TestSuperblock) {
  fbl::unique_fd input_fd;
  fbl::unique_fd output_fd;

  CreateInputAndOutputStream(fs(), input_fd, output_fd, nullptr);
  Extract(input_fd, output_fd, false);

  blobfs::Superblock info;
  VerifyInputSuperblock(&info, input_fd);

  struct stat stats;
  ASSERT_EQ(fstat(output_fd.get(), &stats), 0);
  VerifyOutputSuperblock(&info, output_fd);
}

TEST_P(BlobfsExtractionTest, TestCorruptedSuperblock) {
  fbl::unique_fd input_fd;
  fbl::unique_fd output_fd;

  CreateInputAndOutputStream(fs(), input_fd, output_fd, nullptr);
  std::unique_ptr<char[]> original_superblock(new char[blobfs::kBlobfsBlockSize]);
  ASSERT_EQ(pread(input_fd.get(), original_superblock.get(), blobfs::kBlobfsBlockSize, 0),
            (ssize_t)blobfs::kBlobfsBlockSize);
  char corrupt_block[blobfs::kBlobfsBlockSize] = {'C'};
  ssize_t r =
      pwrite(input_fd.get(), corrupt_block, sizeof(corrupt_block), blobfs::kSuperblockOffset);
  ASSERT_EQ(r, (ssize_t)sizeof(corrupt_block));
  Extract(input_fd, output_fd, true);

  std::unique_ptr<char[]> superblock(new char[blobfs::kBlobfsBlockSize]);
  ASSERT_EQ(pread(input_fd.get(), superblock.get(), blobfs::kBlobfsBlockSize, 0),
            (ssize_t)blobfs::kBlobfsBlockSize);
  std::unique_ptr<char[]> read_buffer_sb(new char[blobfs::kBlobfsBlockSize]);
  ASSERT_EQ(pread(output_fd.get(), read_buffer_sb.get(), blobfs::kBlobfsBlockSize,
                  kExtractedImageBlockCount * blobfs::kBlobfsBlockSize),
            (ssize_t)blobfs::kBlobfsBlockSize);
  ASSERT_EQ(memcmp(superblock.get(), corrupt_block, blobfs::kBlobfsBlockSize), 0);
  ASSERT_EQ(memcmp(read_buffer_sb.get(), corrupt_block, blobfs::kBlobfsBlockSize), 0);

  // Restore original superblock to pass Fsck test
  ssize_t r1 = pwrite(input_fd.get(), original_superblock.get(), sizeof(corrupt_block),
                      blobfs::kSuperblockOffset);

  ASSERT_GE(r1, 0) << "errno: " << strerror(errno) << std::endl;
}

TEST_P(BlobfsExtractionTest, TestNodeMap) {
  fbl::unique_fd input_fd;
  fbl::unique_fd output_fd;

  CreateInputAndOutputStream(fs(), input_fd, output_fd, nullptr);
  Extract(input_fd, output_fd, false);

  blobfs::Superblock info;
  VerifyInputSuperblock(&info, input_fd);
  ASSERT_EQ(info.alloc_inode_count, 1ul);

  VerifyOutputSuperblock(&info, output_fd);

  std::unique_ptr<blobfs::Inode[]> inode_table;
  inode_table =
      std::make_unique<blobfs::Inode[]>(NodeMapBlocks(info) * blobfs::kBlobfsInodesPerBlock);
  auto size = static_cast<ssize_t>(blobfs::NodeMapBlocks(info) * blobfs::kBlobfsBlockSize);
  ASSERT_EQ(pread(input_fd.get(), inode_table.get(), size,
                  blobfs::kBlobfsBlockSize * blobfs::NodeMapStartBlock(info)),
            size);

  char read_buffer_nodemap[size];
  ASSERT_EQ(pread(output_fd.get(), read_buffer_nodemap, size, NodemapOffset(info)), size);
  ASSERT_EQ(memcmp(inode_table.get(), read_buffer_nodemap, size), 0);
}

TEST_P(BlobfsExtractionTest, TestBlockMap) {
  fbl::unique_fd input_fd;
  fbl::unique_fd output_fd;

  CreateInputAndOutputStream(fs(), input_fd, output_fd, nullptr);
  Extract(input_fd, output_fd, false);

  blobfs::Superblock info;
  VerifyInputSuperblock(&info, input_fd);
  ASSERT_EQ(info.alloc_inode_count, 1ul);

  VerifyOutputSuperblock(&info, output_fd);

  auto size = static_cast<ssize_t>(blobfs::BlockMapBlocks(info) * blobfs::kBlobfsBlockSize);
  char block_bitmap[size];
  ASSERT_EQ(pread(input_fd.get(), block_bitmap, size,
                  blobfs::kBlobfsBlockSize * blobfs::BlockMapStartBlock(info)),
            size);

  char read_buffer_blockmap[size];
  ASSERT_EQ(pread(output_fd.get(), read_buffer_blockmap, size, BlockBitmapOffset(info)), size);
  ASSERT_EQ(memcmp(block_bitmap, read_buffer_blockmap, size), 0);
}

TEST_P(BlobfsExtractionTest, TestJournal) {
  fbl::unique_fd input_fd;
  fbl::unique_fd output_fd;

  CreateInputAndOutputStream(fs(), input_fd, output_fd, nullptr);
  Extract(input_fd, output_fd, false);

  blobfs::Superblock info;

  VerifyInputSuperblock(&info, input_fd);
  ASSERT_EQ(info.alloc_inode_count, 1ul);

  VerifyOutputSuperblock(&info, output_fd);

  auto size = static_cast<ssize_t>(blobfs::JournalBlocks(info) * blobfs::kBlobfsBlockSize);
  std::unique_ptr<char[]> journal(new char[size]);
  ASSERT_EQ(pread(input_fd.get(), journal.get(), size,
                  blobfs::kBlobfsBlockSize * blobfs::JournalStartBlock(info)),
            size);

  std::unique_ptr<char[]> read_buffer_blockmap(new char[size]);
  ASSERT_EQ(pread(output_fd.get(), read_buffer_blockmap.get(), size, JournalOffset(info)), size);
  ASSERT_EQ(memcmp(journal.get(), read_buffer_blockmap.get(), size), 0);
}

TEST_P(BlobfsExtractionTest, TestCorruptBlob) {
  fbl::unique_fd input_fd;
  fbl::unique_fd output_fd;
  std::unique_ptr<blobfs::BlobInfo> blob_info;
  CreateInputAndOutputStream(fs(), input_fd, output_fd, &blob_info);

  blobfs::Superblock info;
  VerifyInputSuperblock(&info, input_fd);
  ASSERT_EQ(int(info.alloc_inode_count), 1);

  std::unique_ptr<blobfs::Inode[]> inode_table;
  inode_table =
      std::make_unique<blobfs::Inode[]>(NodeMapBlocks(info) * blobfs::kBlobfsInodesPerBlock);
  auto nodemap_size = static_cast<ssize_t>(blobfs::NodeMapBlocks(info) * blobfs::kBlobfsBlockSize);
  ASSERT_EQ(nodemap_size, pread(input_fd.get(), inode_table.get(), nodemap_size,
                                blobfs::kBlobfsBlockSize * blobfs::NodeMapStartBlock(info)));
  uint64_t input_datablock_offset = 0;
  bool found_allocated_inode = false;
  uint64_t size_of_data;
  for (unsigned n = 0; n < info.inode_count; n++) {
    blobfs::Inode ino = inode_table[n];
    blobfs::NodePrelude header = ino.header;
    if (header.IsAllocated() && header.IsInode()) {
      blobfs::Extent extent = ino.extents[0];
      input_datablock_offset = extent.Start();
      size_of_data = extent.Length() * blobfs::kBlobfsBlockSize;
      found_allocated_inode = true;
      break;
    }
  }
  ASSERT_EQ(found_allocated_inode, true);
  char corrupt_block[blobfs::kBlobfsBlockSize] = {'C'};
  // Assuming here that merkle tree is at the beginning and only takes up one block woo
  auto offset = static_cast<off_t>((blobfs::DataStartBlock(info) + input_datablock_offset + 1)) *
                static_cast<off_t>(blobfs::kBlobfsBlockSize);
  ssize_t r = pwrite(input_fd.get(), corrupt_block, sizeof(corrupt_block), offset);
  ASSERT_EQ(r, (ssize_t)sizeof(corrupt_block));

  Extract(input_fd, output_fd, false);
  VerifyOutputSuperblock(&info, output_fd);

  struct stat stats;
  ASSERT_EQ(fstat(output_fd.get(), &stats), 0);
  char read_buffer_datablocks[size_of_data];
  ASSERT_EQ(pread(output_fd.get(), read_buffer_datablocks, size_of_data, DatablockOffset(info)),
            ssize_t(size_of_data));

  // Assuming that the merkle tree takes up the first block of read_buffer_datablocks
  ASSERT_NE(memcmp(blob_info->data.get(), read_buffer_datablocks + blobfs::kBlobfsBlockSize,
                   size_of_data - blobfs::kBlobfsBlockSize),
            0);

  ASSERT_EQ(memcmp(blob_info->data.get() + blobfs::kBlobfsBlockSize,
                   read_buffer_datablocks + (2 * blobfs::kBlobfsBlockSize),
                   size_of_data - (2 * blobfs::kBlobfsBlockSize)),
            0);

  offset = static_cast<off_t>((blobfs::DataStartBlock(info) + input_datablock_offset + 1)) *
           static_cast<off_t>(blobfs::kBlobfsBlockSize);
  ssize_t r1 = pwrite(input_fd.get(), blob_info->data.get(), sizeof(corrupt_block), offset);

  ASSERT_GE(r1, 0) << "errno: " << strerror(errno) << std::endl;
}

// This test depends on the "padded" blobfs format. It will need updating to test compact.
INSTANTIATE_TEST_SUITE_P(/*no prefix*/, BlobfsExtractionTest,
                         testing::Values(blobfs::BlobfsWithPaddedLayoutTestParam()),
                         testing::PrintToStringParamName());
}  // namespace

}  // namespace extractor
