text: // 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.
  
  #ifndef SRC_STORAGE_MINFS_MINFS_INSPECTOR_H_
  #define SRC_STORAGE_MINFS_MINFS_INSPECTOR_H_
  
  #include <string>
  #include <vector>
  
  #include <block-client/cpp/block-device.h>
  #include <disk_inspector/buffer_factory.h>
  #include <disk_inspector/common_types.h>
  #include <disk_inspector/inspector_transaction_handler.h>
  
  #include "src/lib/storage/vfs/cpp/journal/format.h"
  #include "src/storage/minfs/format.h"
  
  namespace minfs {
  
  // Bare-bone minfs inspector that loads metadata from the backing block
  // device and provides functions to return parsed structs.
  // TODO(fxbug.dev/47359): Since this can run on corrupt data, more thought needs
  // to be put on the potential edge cases that can happen during corruption.
  // Care needs to be put into what dependencies are used when exposing new
  // information from this class.
  class MinfsInspector {
   public:
    // Creates a MinfsInspector from a block device. Tries to load the
    // superblock from disk upon creation by calling ReloadSuperblock().
    static fit::result<std::unique_ptr<MinfsInspector>, zx_status_t> Create(
        std::unique_ptr<fs::TransactionHandler> handler,
        std::unique_ptr<disk_inspector::BufferFactory> factory);
  
    // This function is used to initialize minfs metadata buffers and to load the relavent data.
    zx_status_t Initialize();
  
    // Initializes the |superblock_| buffer and tries to load the superblock
    // from disk into the buffer. The MinfsInspector should be considered invalid
    // and should not be used if this function fails as either VmoBuffers cannot
    // be created or we cannot read even the first block from the underlying
    // block device.
    zx_status_t ReloadSuperblock();
  
    // Initializes the |inode_bitmap_|, |inode_table_|, and |journal_| buffers
    // based on |superblock_| and tries to load the associated structs from disk
    // into these buffers. Note: we do not consider the failure of initializing
    // and loading of any of these buffers to be errors to crash the program as
    // the class should still work to a reasonable degree in the case of debugging
    // a superblock with corruptions. For cases of failure, these bufffers have
    // undefined size and data inside. It is up to users to make sure that they
    // make valid calls using other functions in this class.
    void ReloadMetadataFromSuperblock();
  
    // Returns a copy of |superblock_|.
    Superblock InspectSuperblock();
  
    // Returns the number of inodes from |superblock_|.
    uint64_t GetInodeCount();
  
    // Returns the number of journal entires calculated from |superblock_|.
    uint64_t GetJournalEntryCount();
  
    // The following functions need to load data from disk, leading to the
    // possibility of failed loads. Since they need to return values, we have
    // fit::results for all of the return types. In addition, they all depend
    // on the loaded |superblock_| value to get where to start indexing.
  
    // Loads the inode table blocks for which the inodes from |start_index| inclusive
    // to |end_index| exclusive from disk and returns the Inodes in the range as
    // a vector.
    fit::result<std::vector<Inode>, zx_status_t> InspectInodeRange(uint64_t start_index,
                                                                   uint64_t end_index);
  
    // Loads the inode bitmap blocks for which the inode allocation bits for inodes
    // from |start_index| inclusive to |end_index| exclusive from disk and returns
    // the inode indices for which the corresponding bits are allocated.
    fit::result<std::vector<uint64_t>, zx_status_t> InspectInodeAllocatedInRange(uint64_t start_index,
                                                                                 uint64_t end_index);
  
    // Loads the first journal block
    fit::result<fs::JournalInfo, zx_status_t> InspectJournalSuperblock();
  
    // Loads the |index| element journal entry block and returns it as a struct
    // of type T. Only supports casting to fs::JournalPrefix, fs::JournalHeaderBlock,
    // and fs::JournalCommitBlock.
    template <typename T>
    fit::result<T, zx_status_t> InspectJournalEntryAs(uint64_t index);
  
    // Loads and returns the backup superblock.
    fit::result<Superblock, zx_status_t> InspectBackupSuperblock();
  
    // Writes the |superblock| argument to disk and sets |superblock_| to |superblock|
    // if the write succeeds.
    fit::result<void, zx_status_t> WriteSuperblock(Superblock superblock);
  
   private:
    explicit MinfsInspector(std::unique_ptr<fs::TransactionHandler> handler,
                            std::unique_ptr<disk_inspector::BufferFactory> buffer_factory);
  
    zx_status_t LoadJournalEntry(storage::BlockBuffer* buffer, uint64_t index);
  
    std::unique_ptr<fs::TransactionHandler> handler_;
    std::unique_ptr<disk_inspector::BufferFactory> buffer_factory_;
    Superblock superblock_;
    // Scratch buffer initialized to be a single block in the Create method.
    // Functions that use this buffer should try to treat it as an initialized
    // buffer only valid for the duration of the function without any presaved
    // state or ability for the function to save state.
    std::unique_ptr<storage::BlockBuffer> buffer_;
  };
  
  }  // namespace minfs
  
  #endif  // SRC_STORAGE_MINFS_MINFS_INSPECTOR_H_
  