// Copyright 2019 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 <minfs/inspector.h>

#include <sys/stat.h>

#include <fbl/unique_fd.h>
#include <lib/disk-inspector/common-types.h>
#include <minfs/bcache.h>

#include "inspector-private.h"

namespace minfs {

namespace {
std::unique_ptr<disk_inspector::DiskObjectUint64> CreateUint64DiskObj(fbl::String fieldName,
                                                                      const uint64_t* value) {
    return std::make_unique<disk_inspector::DiskObjectUint64>(fieldName, value);
}

std::unique_ptr<disk_inspector::DiskObjectUint32> CreateUint32DiskObj(fbl::String fieldName,
                                                                      const uint32_t* value) {
    return std::make_unique<disk_inspector::DiskObjectUint32>(fieldName, value);
}

std::unique_ptr<disk_inspector::DiskObjectUint64Array> CreateUint64ArrayDiskObj(
                                                                     fbl::String fieldName,
                                                                     const uint64_t* value,
                                                                     size_t size) {
    return std::make_unique<disk_inspector::DiskObjectUint64Array>(fieldName, value, size);
}

std::unique_ptr<disk_inspector::DiskObjectUint32Array> CreateUint32ArrayDiskObj(
                                                                    fbl::String fieldName,
                                                                    const uint32_t* value,
                                                                    size_t size) {
    return std::make_unique<disk_inspector::DiskObjectUint32Array>(fieldName, value, size);
}

} // namespace

void InodeObject::GetValue(const void** out_buffer, size_t* out_buffer_size) const {
    ZX_DEBUG_ASSERT_MSG(false, "Invalid GetValue call for non primitive data type.");
}

std::unique_ptr<disk_inspector::DiskObject> InodeObject::GetElementAt(uint32_t index) const {
    switch (index) {
        case 0: {
            // uint32_t magic
            return CreateUint32DiskObj("magic", &(inode_.magic));
        }
        case 1: {
            // uint32_t size
            return CreateUint32DiskObj("size", &(inode_.size));
        }
        case 2: {
            // uint32_t block_count
            return CreateUint32DiskObj("block_count", &(inode_.block_count));
        }
        case 3: {
            // uint32_t link_count
            return CreateUint32DiskObj("link_count", &(inode_.link_count));
        }
        case 4: {
            // uint64_t create_time
            return CreateUint64DiskObj("create_time", &(inode_.create_time));
        }
        case 5: {
            // uint64_t modify_time
            return CreateUint64DiskObj("modify_time", &(inode_.modify_time));
        }
        case 6: {
            // uint32_t seq_num
            return CreateUint32DiskObj("seq_num", &(inode_.seq_num));
        }
        case 7: {
            // uint32_t gen_num
            return CreateUint32DiskObj("gen_num", &(inode_.gen_num));
        }
        case 8: {
            // uint32_t dirent_count
            return CreateUint32DiskObj("dirent_count", &(inode_.dirent_count));
        }
        case 9: {
            // ino_t/uint32_t last_inode
            return CreateUint32DiskObj("last_inode", &(inode_.last_inode));
        }
        case 10: {
            // ino_t/uint32_t next_inode
            return CreateUint32DiskObj("next_inode", &(inode_.next_inode));
        }
        case 11: {
            //uint32_t Array rsvd
            return CreateUint32ArrayDiskObj("reserved", inode_.rsvd, 3);
        }
        case 12: {
            // blk_t/uint32_t Array dnum
            return CreateUint32ArrayDiskObj("direct blocks", inode_.dnum, kMinfsDirect);
        }
        case 13: {
            // blk_t/uint32_t Array inum
            return CreateUint32ArrayDiskObj("indirect blocks", inode_.inum, kMinfsIndirect);
        }
        case 14: {
            // blk_t/uint32_t Array dinum
            return CreateUint32ArrayDiskObj("double indirect blocks", inode_.dinum,
                                            kMinfsDoublyIndirect);
        }
    }
    return nullptr;
}

void InodeTableObject::GetValue(const void** out_buffer, size_t* out_buffer_size) const {
    ZX_DEBUG_ASSERT_MSG(false, "Invalid GetValue call for non primitive data type.");
}

std::unique_ptr<disk_inspector::DiskObject> InodeTableObject::GetElementAt(uint32_t index) const {
    if (index >= inode_count_) {
        return nullptr;
    }
    return GetInode(static_cast<ino_t>(index));
}

std::unique_ptr<disk_inspector::DiskObject> InodeTableObject::GetInode(ino_t inode) const {
    Inode inode_obj;
    inode_table_->Load(inode, &inode_obj);
    return std::unique_ptr<disk_inspector::DiskObject>(new InodeObject(inode_obj));
}

void SuperBlockObject::GetValue(const void** out_buffer, size_t* out_buffer_size) const {
    ZX_DEBUG_ASSERT_MSG(false, "Invalid GetValue call for non primitive data type.");
}

std::unique_ptr<disk_inspector::DiskObject> SuperBlockObject::GetElementAt(uint32_t index) const {
    switch (index) {
        case 0: {
            // uint64_t magic0
            return CreateUint64DiskObj("magic0", &(sb_.magic0));
        }
        case 1: {
            // uint64_t magic1
            return CreateUint64DiskObj("magic1", &(sb_.magic1));
        }
        case 2: {
            // uint32_t version
            return CreateUint32DiskObj("version", &(sb_.version));
        }
        case 3: {
            // uint32_t flags
            return CreateUint32DiskObj("flags", &(sb_.flags));
        }
        case 4: {
            // uint32_t block_size
            return CreateUint32DiskObj("block_size", &(sb_.block_size));
        }
        case 5: {
            // uint32_t inode_size
            return CreateUint32DiskObj("inode_size", &(sb_.inode_size));
        }
        case 6: {
            // uint32_t block_count
            return CreateUint32DiskObj("block_count", &(sb_.block_count));
        }
        case 7: {
            // uint32_t inode_count
            return CreateUint32DiskObj("inode_count", &(sb_.inode_count));
        }
        case 8: {
            // uint32_t alloc_block_count
            return CreateUint32DiskObj("alloc_block_count",
                        &(sb_.alloc_block_count));
        }
        case 9: {
            // uint32_t alloc_inode_count
            return CreateUint32DiskObj("alloc_inode_count", &(sb_.alloc_inode_count));
        }
        case 10: {
            // uint32_t/blk_t ibm_block
            return CreateUint32DiskObj("ibm_block", &(sb_.ibm_block));
        }
        case 11: {
            // uint32_t/blk_t abm_block
            return CreateUint32DiskObj("abm_block", &(sb_.abm_block));
        }
        case 12: {
            // uint32_t/blk_t ino_block
            return CreateUint32DiskObj("ino_block", &(sb_.ino_block));
        }
        case 13: {
            // uint32_t/blk_t journal_start_block
            return CreateUint32DiskObj("journal_start_block", &(sb_.journal_start_block));
        }
        case 14: {
            // uint32_t/blk_t dat_block
            return CreateUint32DiskObj("dat_block", &(sb_.dat_block));
        }
        case 15: {
            // uint64_t slice_size
            return CreateUint64DiskObj("slice_size", &(sb_.slice_size));
        }
        case 16: {
            // uint64_t vslice_count
            return CreateUint64DiskObj("vslice_count", &(sb_.vslice_count));
        }
        case 17: {
            // uint32_t ibm_slices
            return CreateUint32DiskObj("ibm_slices", &(sb_.ibm_slices));
        }
        case 18: {
            // uint32_t abm_slices
            return CreateUint32DiskObj("abm_slices", &(sb_.abm_slices));
        }
        case 19: {
            // uint32_t ino_slices
            return CreateUint32DiskObj("ino_slices", &(sb_.ino_slices));
        }
        case 20: {
            // uint32_t journal_slices
            return CreateUint32DiskObj("journal_slices", &(sb_.journal_slices));
        }
        case 21: {
            // uint32_t dat_slices
            return CreateUint32DiskObj("dat_slices", &(sb_.dat_slices));
        }
        case 22: {
            // uint32_t/ino_t unlinked_head
            return CreateUint32DiskObj("unlinked_head", &(sb_.unlinked_head));
        }
        case 23: {
            // uint32_t/ino_t unlinked_tail
            return CreateUint32DiskObj("unlinked_tail", &(sb_.unlinked_tail));
        }
    }
    return nullptr;
}

void JournalObject::GetValue(const void** out_buffer, size_t* out_buffer_size) const  {
    ZX_DEBUG_ASSERT_MSG(false, "Invalid GetValue call for non primitive data type.");
}

std::unique_ptr<disk_inspector::DiskObject> JournalObject::GetElementAt(uint32_t index) const {
    switch (index) {
        case 0: {
            // uint64_t magic
            return CreateUint64DiskObj("magic", &(journal_info_->magic));
        }
        case 1: {
            // uint64_t reserved0
            return CreateUint64DiskObj("reserved0", &(journal_info_->reserved0));
        }
        case 2: {
            // uint64_t reserved1
            return CreateUint64DiskObj("reserved1", &(journal_info_->reserved1));
        }
        case 3: {
            // uint64_t reserved2
            return CreateUint64DiskObj("reserved2", &(journal_info_->reserved2));
        }
        case 4: {
            // uint64_t reserved3
            return CreateUint64DiskObj("reserved3", &(journal_info_->reserved3));
        }
    }
    return nullptr;
}

zx_status_t Inspector::GetRoot(std::unique_ptr<disk_inspector::DiskObject> *out) {
    std::unique_ptr<minfs::Bcache> bc;
    struct stat stats;
    if (fstat(fd_.get(), &stats) < 0) {
        fprintf(stderr, "minfsInspector: could not find end of file/device\n");
        return ZX_ERR_IO;
    }

    if (stats.st_size == 0) {
        fprintf(stderr, "minfsInspector: invalid disk size\n");
        return ZX_ERR_IO;
    }

    size_t size = stats.st_size / minfs::kMinfsBlockSize;

    if (minfs::Bcache::Create(&bc, std::move(fd_), static_cast<uint32_t>(size)) < 0) {
        fprintf(stderr, "minfsInspector: cannot create block cache\n");
        return ZX_ERR_IO;
    }

    zx_status_t status = CreateRoot(std::move(bc), out);
    if (status != ZX_OK) {
        fprintf(stderr, "minfsInspector: cannot create root object\n");
        return status;
    }
    return ZX_OK;
}

zx_status_t Inspector::CreateRoot(std::unique_ptr<Bcache> bc,
                                  std::unique_ptr<disk_inspector::DiskObject>* out) {
    zx_status_t status = ZX_OK;
    char data[kMinfsBlockSize];
    if (bc->Readblk(0, data) < 0) {
        FS_TRACE_ERROR("minfsInspector: could not read superblock\n");
        return ZX_ERR_IO;
    }
    const Superblock* info = reinterpret_cast<const Superblock*>(data);
    std::unique_ptr<Minfs> fs;
    if ((status = Minfs::Create(std::move(bc), info, &fs, IntegrityCheck::kNone)) != ZX_OK) {
        FS_TRACE_ERROR("minfsInspector: Create Failed to Create Minfs: %d\n", status);
        return status;
    }
    *out = std::unique_ptr<disk_inspector::DiskObject>(new RootObject(std::move(fs)));
    return ZX_OK;
}

std::unique_ptr<disk_inspector::DiskObject> RootObject::GetSuperBlock() const {
    return std::unique_ptr<disk_inspector::DiskObject>(new SuperBlockObject(fs_->Info()));
}

std::unique_ptr<disk_inspector::DiskObject> RootObject::GetInodeTable() const {
    return std::unique_ptr<disk_inspector::DiskObject>(new InodeTableObject(fs_->GetInodeManager(),
                                                       fs_->Info().alloc_inode_count));
}

std::unique_ptr<disk_inspector::DiskObject> RootObject::GetJournalInfo() const {
    char data[kMinfsBlockSize];

    if (fs_->ReadBlock(fs_->Info().journal_start_block, data) < 0) {
        FS_TRACE_ERROR("minfsInspector: could not read journal block\n");
        return nullptr;
    }

    JournalInfo* info = reinterpret_cast<JournalInfo*>(data);
    std::unique_ptr<JournalInfo> journal_info(new JournalInfo);
    memcpy(journal_info.get(), info, sizeof(*info));
    return std::unique_ptr<disk_inspector::DiskObject>(new JournalObject(std::move(journal_info)));
}

void RootObject::GetValue(const void** out_buffer, size_t* out_buffer_size) const {
    ZX_DEBUG_ASSERT_MSG(false, "Invalid GetValue call for non primitive data type.");
}

std::unique_ptr<disk_inspector::DiskObject> RootObject::GetElementAt(uint32_t index) const {
    switch (index) {
        case 0: {
            // Super Block
            return GetSuperBlock();
        }
        case 1: {
            // Inode Table
            return GetInodeTable();
        }
        case 2: {
            // Journal
            return GetJournalInfo();
        }
    };
    return nullptr;
}

} // namespace minfs
