diff --git a/src/fs.cpp b/src/fs.cpp index f99d5e6..0c31133 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -8,8 +8,6 @@ namespace vc5::filesys { -using BlockData = std::array; - namespace { auto inode_mode(INodeType type) -> u16 @@ -115,7 +113,7 @@ auto Fs::append_to_directory(INode& dir_inode, const DirEntry& entry) for (u16 i = 0; i < inode_ndir_blocks; ++i) { auto dir_entry_block = dir_inode.blocks[i]; - auto block = read_block(dir_entry_block); + auto block = read_block>(dir_entry_block); if (not block) return std::unexpected(block.error()); } @@ -155,11 +153,11 @@ auto Fs::inode_last_block_id(const INode& inode) -> Result auto block_id = inode.blocks[inode_ind_block]; assert(block_id != 0); - auto ind_block = read_block(block_id); + auto ind_block = read_block>(block_id); if (not ind_block) return std::unexpected(ind_block.error()); - return ind_block.value()[inode.blocks_count - inode_ind_block]; + return ind_block->data[inode.blocks_count - inode_ind_block]; } else if (inode.blocks_count == inode_dind_block) { @@ -169,18 +167,18 @@ auto Fs::inode_last_block_id(const INode& inode) -> Result auto first_block_id = inode.blocks[inode_dind_block]; assert(first_block_id != 0); - auto first_ind_block = read_block(first_block_id); + auto first_ind_block = read_block>(first_block_id); if (not first_ind_block) return std::unexpected(first_ind_block.error()); auto second_block_id - = first_ind_block.value()[inode.blocks_count - inode_dind_block]; + = first_ind_block->data[inode.blocks_count - inode_dind_block]; - auto second_ind_block = read_block(second_block_id); + auto second_ind_block = read_block>(second_block_id); if (not second_ind_block) return std::unexpected(second_ind_block.error()); - return second_ind_block.value()[inode.blocks_count - inode_dind_block]; + return second_ind_block->data[inode.blocks_count - inode_dind_block]; } else { return std::unexpected("inode at capacity"); @@ -299,6 +297,95 @@ auto Fs::sync_to_disk() -> Result return {}; } +class BeWriter { +public: + template + BeWriter(Data* data) + : m_data(reinterpret_cast(data)) {}; + + template + requires std::is_integral_v + auto operator<<(Int v) -> BeWriter& + { + for (std::size_t i = 0; i < sizeof(Int); ++i) { + *m_data = v >> (sizeof(Int) - i - 1) * 8 & 0xff; + m_data++; + } + return *this; + } + + template + requires(size % 8 == 0) + auto operator<<(const std::bitset& bitmap) -> BeWriter& + { + for (std::size_t bit = 0; bit < bitmap.size(); bit += 8) { + u8 v = 0; + for (std::size_t i = 0; i < 8; ++i) + v |= bitmap[bit + i] << i; + *this << v; + } + return *this; + } + + template + requires std::is_integral_v + auto operator<<(const std::array& array) -> BeWriter& + { + for (auto elem : array) + *this << elem; + return *this; + } + +private: + u8* m_data; +}; + +class BeReader { +public: + template + BeReader(const Data* data) + : m_data(reinterpret_cast(data)) {}; + + template + requires std::is_integral_v + auto operator>>(Int& v) -> BeReader& + { + v = 0; + for (std::size_t i = 0; i < sizeof(Int); ++i) { + v |= *m_data << (sizeof(Int) - i - 1) * 8; + m_data++; + } + return *this; + } + + template + requires(size % 8 == 0) + auto operator>>(std::bitset& bitmap) -> BeReader& + { + for (std::size_t bit = 0; bit < bitmap.size(); bit += 8) { + u8 v; + *this >> v; + for (std::size_t i = 0; i < 8; ++i) + bitmap[bit + i] = v >> i & 1; + } + return *this; + } + + template + requires std::is_integral_v + auto operator>>(std::array& array) -> BeReader& + { + for (auto& elem : array) + *this >> elem; + return *this; + } + +private: + const u8* m_data; +}; + +using BlockData = std::array; + template requires(sizeof(Data) <= block_size) auto Fs::read_block_part(u16 block_id, u16 offset) -> Result @@ -325,9 +412,9 @@ auto Fs::write_block_part(u16 block_id, const Data& data, u16 offset) BlockData block = {}; m_disk->read(block.data(), block_id); - std::memcpy(block.data(), - reinterpret_cast(&data) + offset, - sizeof(Data)); + auto writer = BeWriter(block.data() + offset); + data.write(writer); + m_disk->write(block.data(), block_id); return {}; @@ -340,8 +427,10 @@ auto Fs::read_block(u16 block_id) -> Result BlockData block = {}; m_disk->read(block.data(), block_id); + auto reader = BeReader(block.data()); + Data data; - std::memcpy(reinterpret_cast(&data), block.data(), sizeof(Data)); + data.read(reader); return data; } @@ -351,8 +440,10 @@ template auto Fs::write_block(const Data& data, u16 block_id) -> Result { BlockData block = {}; - std::memcpy( - block.data(), reinterpret_cast(&data), sizeof(Data)); + + auto writer = BeWriter(block.data()); + data.write(writer); + m_disk->write(block.data(), block_id); return {}; } diff --git a/src/fs.hpp b/src/fs.hpp index cee7292..8a99ed6 100644 --- a/src/fs.hpp +++ b/src/fs.hpp @@ -3,6 +3,7 @@ #include "block_device.hpp" #include "types.hpp" #include +#include #include #include #include @@ -20,6 +21,16 @@ struct DirEntry { u16 next; u16 name_len; std::array name; + + template void write(Writer& w) const + { + w << inode << next << name_len << name; + } + + template auto read(Reader& r) + { + r >> inode >> next >> name_len >> name; + } }; constexpr u16 inode_size = 32; @@ -46,6 +57,18 @@ struct INode { u16 last_block_size; u32 size; std::array blocks; + + template void write(Writer& w) const + { + w << mode << blocks_count << links_count << last_block_size << size + << blocks; + } + + template auto read(Reader& r) + { + r >> mode >> blocks_count >> links_count >> last_block_size >> size + >> blocks; + } }; static_assert(sizeof(INode) <= inode_size); @@ -65,12 +88,50 @@ struct Superblock { u16 inode_blocks_count; std::array iblocks; std::bitset inode_bitmap; + + template void write(Writer& w) const + { + w << volume_id << fs_version << blocks_count << blocks_free + << root_inode << inode_blocks_count << iblocks << inode_bitmap; + } + + template auto read(Reader& r) + { + r >> volume_id >> fs_version >> blocks_count >> blocks_free + >> root_inode >> inode_blocks_count >> iblocks >> inode_bitmap; + } }; static_assert(sizeof(Superblock) <= block_size); struct BlocksBitmap { std::bitset bitmap; + + template void write(Writer& w) const + { + w << bitmap; + } + + template auto read(Reader& r) + { + r >> bitmap; + } +}; + +template + requires std::is_integral_v +struct IntBlock { + std::array data; + + template void write(Writer& w) const + { + w << data; + } + + template auto read(Reader& r) + { + r >> data; + } }; static_assert(sizeof(BlocksBitmap) <= block_size);