diff --git a/src/fs.cpp b/src/fs.cpp index 535ecb6..587793c 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -1,10 +1,12 @@ #include "fs.hpp" +#include "block_device.hpp" #include -#include +#include #include #include #include #include +#include namespace vc5::filesys { @@ -13,16 +15,10 @@ namespace { auto inode_mode(INodeType type) -> u16 { u16 mode = 0; - mode |= std::to_underlying(type) << inode_type_bitoffset; + mode |= std::to_underlying(type) << INode::type_bitoffset; return mode; } - auto inode_mode_type(u16 mode) -> INodeType - { - return static_cast( - mode >> inode_type_bitoffset & inode_type_bitmask); - } - auto unwrap_inode_id(u16 inode_id) -> std::tuple { u16 inode_block_idx = inode_id / inodes_per_block; @@ -37,234 +33,244 @@ namespace { } -auto Fs::init_new(u16 volume_id, u16 block_count) -> Result +auto Fs::init(u16 volume_id, u16 block_count) -> void { m_superblock = Superblock { .volume_id = volume_id, .fs_version = 1, - .blocks_count = block_count, + .blocks_count = 0, .blocks_free = block_count, .root_inode = 0, .inode_blocks_count = 0, - .iblocks = {}, + .inode_blocks = {}, .inode_bitmap = {}, }; - auto root_inode_id = make_directory_inode(); - if (not root_inode_id) - return std::unexpected(root_inode_id.error()); + m_blocks_bitmap = {}; + m_blocks_bitmap.bitmap[0] = true; + m_blocks_bitmap.bitmap[1] = true; + m_blocks_bitmap.bitmap[sb_loc] = true; + m_blocks_bitmap.bitmap[blocks_bitmap_loc] = true; - m_superblock.root_inode = *root_inode_id; + auto root_inode_id = allocate_inode(); + auto root_inode = make_dir_with_inode_ids(root_inode_id, root_inode_id); + (void)root_inode; - if (auto result = sync_to_disk(); not result) - return result; + m_superblock.root_inode = root_inode_id; - return {}; + m_out_of_sync = true; + sync_to_disk(); } -auto Fs::init_from_existing() -> Result +auto Fs::load() -> void { - return sync_from_disk(); + m_superblock = read_block(sb_loc); + m_blocks_bitmap = read_block(blocks_bitmap_loc); + m_out_of_sync = false; } -auto Fs::make_file(u16 parent_inode_id, std::string_view name) -> Result +auto Fs::root_inode() -> INode { - return make_inode(parent_inode_id, name, INodeType::Dir); + return read_inode(m_superblock.root_inode); } -auto Fs::make_directory(u16 parent_inode_id, std::string_view name) - -> Result +auto Fs::make_dir(INode& parent, std::string_view name) -> INode +{ + auto inode_id = allocate_inode(); + auto inode = make_dir_with_inode_ids(inode_id, parent.id); + write_inode(inode); + add_inode_to_dir(parent, inode, name); + sync_to_disk(); + return inode; +} + +auto Fs::make_file(INode& parent, std::string_view name) -> INode { - return make_inode(parent_inode_id, name, INodeType::Dir); -} - -// auto Fs::write(u16 inode_id, const void* data, u16 size) -> Result -// { -// auto inode_result = read_inode(inode_id); -// if (not inode_result) -// return std::unexpected(inode_result.error()); -// auto& inode = *inode_result; -// -// if (auto result = inode_for_each_block_id(inode, -// [&](u16& block_id) { -// deallocate_block(block_id); -// block_id = 0; -// }); -// not result) -// return std::unexpected(result.error()); -// } - -auto Fs::make_inode(u16 parent_inode_id, std::string_view name, INodeType type) - -> Result -{ - if (name.size() > name_max_len) - return std::unexpected("invalid filename"); - auto inode_id = allocate_inode(); - if (not inode_id) - return inode_id; auto inode = INode { - .mode = inode_mode(type), + .id = inode_id, + .mode = inode_mode(INodeType::File), .blocks_count = 0, .links_count = 0, - .last_block_size = 0, .size = 0, + .last_block_size = 0, .blocks = {}, }; + write_inode(inode); + add_inode_to_dir(parent, inode, name); + sync_to_disk(); + return inode; +} + +template + requires ReturnsControlFlow +auto Fs::inode_foreach_block(INode& inode, Func func) -> void +{ + using ControlFlow::Break; + + for (u16 i = 0; i < inode.blocks_count && i < INode::ndir_blocks; ++i) { + if (func(inode.blocks[i]) == Break) { + return; + } + } + + auto block_id = inode.blocks[INode::ind_block]; + assert(block_id != 0); + + auto ind_block = read_block(block_id); + + for (u16 i = 0; i < inode.blocks_count - INode::ndir_blocks; ++i) { + if (func(ind_block.values[i]) == Break) { + return; + } + } +} + +void Fs::add_inode_to_dir(INode& dir, const INode& inode, std::string_view name) +{ + if (not dir.is_dir()) { + throw FsError("incorrect inode type"); + } + if (name.size() > 256) { + throw FsError("invalid argument"); + } + auto entry = DirEntry { - .inode = *inode_id, + .inode = inode.id, .next = 0, .name_len = static_cast(name.size()), .name = {}, }; - std::memcpy(entry.name.data(), name.data(), name.size()); - - if (auto result = append_to_directory(parent_inode_id, entry); not result) - return std::unexpected(result.error()); - - if (auto result = write_inode(*inode_id, inode); not result) - return std::unexpected(result.error()); - - return inode_id; + write_dir_entry(dir, entry); + write_inode(dir); } -auto Fs::append_to_directory(u16 dir_inode_id, const DirEntry& entry) - -> Result +auto Fs::make_dir_with_inode_ids(u16 inode_id, u16 parent_inode_id) -> INode { - auto dir_inode_result = read_inode(dir_inode_id); - if (not dir_inode_result) - return std::unexpected(dir_inode_result.error()); - auto& dir_inode = *dir_inode_result; - - if (inode_mode_type(dir_inode.mode) != INodeType::Dir) - return std::unexpected("incorrect inode type"); - - if (dir_inode.blocks_count == inode_last_block - && entry.size() > block_size - dir_inode.last_block_size) { - return std::unexpected("inode at capacity"); - } - - auto last_block_id = inode_last_block_id(dir_inode); - if (not last_block_id) - return std::unexpected(last_block_id.error()); - - if (auto result = write_block_part( - *last_block_id, entry, dir_inode.last_block_size, entry.size()); - not result) - return std::unexpected(result.error()); - - dir_inode.last_block_size += entry.size(); - - if (auto result = write_inode(dir_inode_id, dir_inode); not result) - return std::unexpected(result.error()); - - return {}; -} - -auto Fs::make_directory_inode() -> Result -{ - auto inode_id = allocate_inode(); - if (not inode_id) - return inode_id; - auto inode = INode { + .id = inode_id, .mode = inode_mode(INodeType::Dir), .blocks_count = 0, .links_count = 0, - .last_block_size = 0, .size = 0, + .last_block_size = 0, .blocks = {}, }; + write_inode(inode); - if (auto result = write_inode(*inode_id, inode); not result) - return std::unexpected(result.error()); - - return inode_id; -} - -auto Fs::inode_last_block_id(const INode& inode) -> Result -{ - if (inode.blocks_count < inode_ndir_blocks) { - return inode.blocks_count - 1; - - } else if (inode.blocks_count >= inode_ind_block - && inode.blocks_count <= inode_ind_block + block_size) { - - auto block_id = inode.blocks[inode_ind_block]; - assert(block_id != 0); - - auto ind_block = read_block>(block_id); - if (not ind_block) - return std::unexpected(ind_block.error()); - - return ind_block->data[inode.blocks_count - inode_ind_block]; - - } else { - return std::unexpected("invalid inode"); - } -} - -template -auto Fs::inode_for_each_block_id(const INode& inode, Func func) -> Result -{ - for (u16 i = 0; i < inode.blocks_count && i < inode_ndir_blocks; ++i) { - func(inode.blocks[i]); - } - - auto block_id = inode.blocks[inode_ind_block]; - assert(block_id != 0); - - auto ind_block = read_block>(block_id); - if (not ind_block) - return std::unexpected(ind_block.error()); - - for (u16 i = 0; i < inode.blocks_count - inode_ndir_blocks; ++i) { - func(inode.blocks[i]); - } -} - -auto Fs::read_inode(u16 inode_id) -> Result -{ - auto [inode_block_idx, block_offset] = unwrap_inode_id(inode_id); - - if (inode_block_idx >= m_superblock.inode_blocks_count) - return std::unexpected("inode lookup failed"); - - auto block_id = m_superblock.iblocks[inode_block_idx]; - - struct INodeData { - u16 mode; - u16 blocks_count; - u16 links_count; - u16 last_block_size; - u32 size; - std::array blocks; + auto parent_name = std::string_view(".."); + auto parent_entry = DirEntry { + .inode = parent_inode_id, + .next = 0, + .name_len = static_cast(parent_name.size()), + .name = {}, }; - static_assert(sizeof(INodeData) == sizeof(INode)); + std::memcpy( + parent_entry.name.data(), parent_name.data(), parent_name.size()); + write_dir_entry(inode, parent_entry); - return read_block_part(block_id, block_offset); + return inode; } -auto Fs::write_inode(u16 inode_id, const INode& inode) -> Result +auto Fs::write_dir_entry(INode& dir_inode, const DirEntry& entry) -> void +{ + u16 entry_block_id; + bool new_block = false; + if (dir_inode.last_block_size + entry.size() > block_size) { + entry_block_id = inode_allocate_block(dir_inode); + new_block = true; + } else { + entry_block_id = inode_last_block(dir_inode); + } + + auto entry_block = read_block(entry_block_id); + + if (not new_block) { + u16 offset = 0; + DirEntry entry; + + do { + entry = entry_block.read_entry(offset); + + if (entry.next != 0) { + offset = entry.next; + } + } while (entry.next != 0); + + u16 new_offset = offset + static_cast(entry.size()); + entry.next = new_offset; + + entry_block.write_entry(offset, entry); + entry_block.write_entry(new_offset, entry); + } else { + entry_block.write_entry(0, entry); + } + + write_block(entry_block_id, entry_block); +} + +auto Fs::inode_allocate_block(INode& inode) -> u16 +{ + auto block_id = allocate_block(); + inode.blocks[inode.blocks_count] = block_id; + inode.blocks_count++; + return block_id; +} + +auto Fs::inode_last_block(INode& inode) -> u16 +{ + if (inode.blocks_count == 0) { + auto block_id = allocate_block(); + inode.blocks[0] = block_id; + inode.blocks_count += 1; + return block_id; + } + + if (inode.blocks_count < INode::ndir_blocks) { + return inode.blocks[inode.blocks_count - 1]; + } + + if (inode.blocks_count >= INode::ind_block + && inode.blocks_count - INode::ind_block < block_size) { + + auto ind_block_id = inode.blocks[INode::ind_block]; + assert(ind_block_id != 0); + + auto ind_block = read_block(ind_block_id); + return ind_block.values[inode.blocks_count - INode::ind_block]; + } + + throw FsError("invalid inode"); +} + +auto Fs::read_inode(u16 inode_id) -> INode { auto [inode_block_idx, block_offset] = unwrap_inode_id(inode_id); if (inode_block_idx >= m_superblock.inode_blocks_count) - return std::unexpected("inode lookup failed"); + throw FsError("inode lookup failed"); - auto block_id = m_superblock.iblocks[inode_block_idx]; + auto block_id = m_superblock.inode_blocks[inode_block_idx]; - if (auto result = write_block_part(block_id, inode, block_offset); - not result) - return result; - - return {}; + return read_block(block_id, block_offset); } -auto Fs::allocate_inode() -> Result +auto Fs::write_inode(const INode& inode) -> void +{ + auto [inode_block_idx, block_offset] = unwrap_inode_id(inode.id); + + if (inode_block_idx >= m_superblock.inode_blocks_count) + throw FsError("inode lookup failed"); + + auto block_id = m_superblock.inode_blocks[inode_block_idx]; + + write_block(block_id, inode, block_offset); +} + +auto Fs::allocate_inode() -> u16 { auto inode_id = std::optional(); auto& sb = m_superblock; @@ -277,22 +283,22 @@ auto Fs::allocate_inode() -> Result if (not inode_id) { if (sb.inode_blocks_count >= iblocks_max_count) { - return std::unexpected("inode allocate failed"); + throw FsError("inode allocate failed"); } auto new_block_id = allocate_block(); - if (not new_block_id) - return new_block_id; - sb.iblocks[sb.inode_blocks_count] = *new_block_id; + sb.inode_blocks[sb.inode_blocks_count] = new_block_id; inode_id = sb.inode_blocks_count * 16; sb.inode_blocks_count += 1; } sb.inode_bitmap[*inode_id] = true; + m_out_of_sync = true; + return *inode_id; } -auto Fs::allocate_block() -> Result +auto Fs::allocate_block() -> u16 { u16 block_id = 0; @@ -304,43 +310,27 @@ auto Fs::allocate_block() -> Result } } if (block_id == 0) { - return std::unexpected("allocate block failed"); + throw FsError("allocate block failed"); } m_blocks_bitmap.bitmap[block_id] = true; + m_out_of_sync = true; + return block_id; } void Fs::deallocate_block(u16 block_id) { m_blocks_bitmap.bitmap[block_id] = false; + m_out_of_sync = true; } -auto Fs::sync_from_disk() -> Result +auto Fs::sync_to_disk() -> void { - auto superblock = read_block(sb_loc); - if (not superblock) - return std::unexpected(superblock.error()); - - auto blocks_bitmap = read_block(blocks_bitmap_loc); - if (not blocks_bitmap) - return std::unexpected(superblock.error()); - - m_superblock = *superblock; - m_blocks_bitmap = *blocks_bitmap; - - return {}; -} - -auto Fs::sync_to_disk() -> Result -{ - if (auto result = write_block(m_superblock, sb_loc); not result) - return result; - - if (auto result = write_block(m_blocks_bitmap, blocks_bitmap_loc); - not result) - return result; - - return {}; + if (m_out_of_sync) { + write_block(sb_loc, m_superblock); + write_block(blocks_bitmap_loc, m_blocks_bitmap); + m_out_of_sync = false; + } } class BeWriter { @@ -430,21 +420,31 @@ private: const u8* m_data; }; -using BlockData = std::array; +using RawBlock = std::array; template requires(sizeof(Data) <= block_size) -auto Fs::read_block_part(u16 block_id, u16 offset, u16 size) -> Result +auto Fs::write_block(u16 block_id, const Data& data, size_t offset) -> void { - assert(size + offset <= block_size); + assert(sizeof(Data) + offset <= block_size); - auto block = BlockData {}; + auto block = RawBlock {}; m_disk->read(block.data(), block_id); - auto raw_data = BlockData {}; - std::memcpy(raw_data.data(), block.data() + offset, size); + auto writer = BeWriter(block.data() + offset); + data.write(writer); - auto reader = BeReader(raw_data.data()); + m_disk->write(block.data(), block_id); +} + +template + requires(sizeof(Data) <= block_size) +auto Fs::read_block(u16 block_id, size_t offset) -> Data +{ + auto block = RawBlock {}; + m_disk->read(block.data(), block_id); + + auto reader = BeReader(block.data() + offset); Data data; data.read(reader); @@ -452,54 +452,35 @@ auto Fs::read_block_part(u16 block_id, u16 offset, u16 size) -> Result return data; } -template - requires(sizeof(Data) <= block_size) -auto Fs::write_block_part(u16 block_id, const Data& data, u16 offset, u16 size) - -> Result +void Fs::write_block_raw( + u16 block_id, const void* data, size_t size, size_t offset) { - assert(size + offset <= block_size); + assert(size + offset <= BlockDevice::block_size); - auto raw_data = BlockData {}; + if (size == BlockDevice::block_size && offset == 0) { + return m_disk->write(static_cast(data), block_id); + } - auto writer = BeWriter(raw_data.data()); - data.write(writer); - - auto block = BlockData {}; + auto block = RawBlock {}; m_disk->read(block.data(), block_id); - std::memcpy(block.data() + offset, raw_data.data(), size); + std::memcpy(block.data() + offset, data, size); m_disk->write(block.data(), block_id); - - return {}; } -template - requires(sizeof(Data) <= block_size) -auto Fs::read_block(u16 block_id) -> Result +void Fs::read_block_raw(void* data, size_t size, u16 block_id, size_t offset) { - auto block = BlockData {}; + assert(size + offset <= BlockDevice::block_size); + + if (size == BlockDevice::block_size && offset == 0) { + return m_disk->read(static_cast(data), block_id); + } + + auto block = RawBlock {}; m_disk->read(block.data(), block_id); - auto reader = BeReader(block.data()); - - Data data; - data.read(reader); - - return data; -} - -template - requires(sizeof(Data) <= block_size) -auto Fs::write_block(const Data& data, u16 block_id) -> Result -{ - auto block = BlockData {}; - - auto writer = BeWriter(block.data()); - data.write(writer); - - m_disk->write(block.data(), block_id); - return {}; + std::memcpy(data, block.data() + offset, size); } } diff --git a/src/fs.hpp b/src/fs.hpp index e94180c..74407e5 100644 --- a/src/fs.hpp +++ b/src/fs.hpp @@ -3,42 +3,18 @@ #include "block_device.hpp" #include "types.hpp" #include +#include #include #include -#include +#include +#include #include #include -#include namespace vc5::filesys { constexpr u16 block_size = 0x200; -constexpr u16 name_max_len = 256; - -struct DirEntry { - u16 inode; - 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; - } - - auto size() const -> u16 - { - return sizeof(inode) + sizeof(next) + sizeof(name_len) - + sizeof(char) * name_len; - } -}; - constexpr u16 inode_size = 32; constexpr u16 inodes_per_block = block_size / inode_size; @@ -48,22 +24,23 @@ enum class INodeType : u16 { Link = 2, }; -constexpr u16 inode_type_bitoffset = 0; -constexpr u16 inode_type_bitmask = 0b11; - -constexpr u16 inode_ndir_blocks = 9; -constexpr u16 inode_ind_block = inode_ndir_blocks; -constexpr u16 inode_blocks_count = inode_ind_block + 1; - -constexpr u16 inode_last_block = inode_ndir_blocks + block_size; - struct INode { + static constexpr u16 type_bitoffset = 0; + static constexpr u16 type_bitmask = 0b11; + + static constexpr u16 ndir_blocks = 8; + static constexpr u16 ind_block = ndir_blocks; + static constexpr u16 max_blocks_count = ind_block + 1; + + static constexpr u16 inode_last_block = ndir_blocks + block_size; + + u16 id; u16 mode; u16 blocks_count; u16 links_count; - u16 last_block_size; u32 size; - std::array blocks; + u16 last_block_size; + std::array blocks; template void write(Writer& w) const { @@ -71,11 +48,23 @@ struct INode { << blocks; } - template auto read(Reader& r) + template void read(Reader& r) { r >> mode >> blocks_count >> links_count >> last_block_size >> size >> blocks; } + + auto is_file() const -> bool + { + return static_cast(mode >> type_bitoffset & type_bitmask) + == INodeType::File; + } + + auto is_dir() const -> bool + { + return static_cast(mode >> type_bitoffset & type_bitmask) + == INodeType::Dir; + } }; static_assert(sizeof(INode) <= inode_size); @@ -93,19 +82,19 @@ struct Superblock { u16 blocks_free; u16 root_inode; u16 inode_blocks_count; - std::array iblocks; + std::array inode_blocks; 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; + << root_inode << inode_blocks_count << inode_blocks << inode_bitmap; } - template auto read(Reader& r) + template void read(Reader& r) { r >> volume_id >> fs_version >> blocks_count >> blocks_free - >> root_inode >> inode_blocks_count >> iblocks >> inode_bitmap; + >> root_inode >> inode_blocks_count >> inode_blocks >> inode_bitmap; } }; @@ -119,29 +108,107 @@ struct BlocksBitmap { w << bitmap; } - template auto read(Reader& r) + template void read(Reader& r) { r >> bitmap; } }; +static_assert(sizeof(BlocksBitmap) <= block_size); -template - requires std::is_integral_v -struct IntBlock { - std::array data; +struct DirEntry { + static constexpr u16 name_max_len = 256; + + u16 inode; + u16 next; + u16 name_len; + std::array name; + + template void write(Writer& w) const + { + w << inode << next << name_len; + + for (int i = 0; i < name_len; ++i) { + w << name[i]; + } + } + + template void read(Reader& r) + { + r >> inode >> next >> name_len; + + for (int i = 0; i < name_len; ++i) { + r << name[i]; + } + } + + auto size() const -> u16 + { + return sizeof(inode) + sizeof(next) + sizeof(name_len) + + sizeof(char) * name_len; + } +}; + +struct IndirectionBlock { + std::array values; + + template void read(Reader& r) + { + r >> values; + } + + template void write(Writer& w) const + { + w << values; + } +}; + +struct DirEntryBlock { + std::array data; + + template void read(Reader& r) + { + r >> data; + } template void write(Writer& w) const { w << data; } - template auto read(Reader& r) + inline DirEntry read_entry(u16 offset) { - r >> data; + // it's ok to read into the entire entry + DirEntry entry; + std::memcpy(&entry, + data.data() + offset, + std::min(sizeof(DirEntry), block_size - offset)); + + assert(entry.size() + offset <= block_size); + return entry; + } + + inline void write_entry(u16 offset, const DirEntry& entry) + { + assert(entry.size() + offset <= block_size); + + std::memcpy(data.data() + offset, &entry, entry.size()); } }; -static_assert(sizeof(BlocksBitmap) <= block_size); +enum class ControlFlow { + Continue, + Break, +}; + +template +concept ReturnsControlFlow + = std::invocable && requires(Func func, Args... args) { + { func(args...) } -> std::convertible_to; + }; + +class FsError : public std::runtime_error { + using std::runtime_error::runtime_error; +}; class Fs { public: @@ -149,85 +216,55 @@ public: : m_disk(&disk) { } + auto init(u16 volume_id, u16 block_count) -> void; + auto load() -> void; - template using Result = std::expected; + auto root_inode() -> INode; + auto make_dir(INode& parent, std::string_view name) -> INode; + auto make_file(INode& parent, std::string_view name) -> INode; - static auto init_new(BlockDevice& disk, u16 volume_id, u16 block_count) - -> Result - { - auto fs = Fs(disk); - if (auto result = fs.init_new(volume_id, block_count); not result) - return std::unexpected(result.error()); - return fs; - } - - static auto load(BlockDevice& disk) -> Result - { - auto fs = Fs(disk); - if (auto result = fs.init_from_existing(); not result) - return std::unexpected(result.error()); - return fs; - } - - auto root_inode_id() const -> Result - { - return m_superblock.root_inode; - } - - auto make_file(u16 parent_inode_id, std::string_view name) -> Result; - auto make_directory(u16 parent_inode_id, std::string_view name) - -> Result; - - auto write(u16 inode_id, const void* data, u16 size) -> Result; + auto write(u16 inode_id, const void* data, u16 size) -> u16; private: - auto init_new(u16 volume_id, u16 block_count) -> Result; - auto init_from_existing() -> Result; - - auto make_inode(u16 parent_inode_id, std::string_view name, INodeType type) - -> Result; - - auto append_to_directory(u16 dir_inode_id, const DirEntry& entry) - -> Result; - auto make_directory_inode() -> Result; - - auto inode_last_block_id(const INode& inode) -> Result; - template - auto inode_for_each_block_id(const INode& inode, Func func) -> Result; + requires ReturnsControlFlow + auto inode_foreach_block(INode& inode, Func func) -> void; - auto write_inode(u16 inode_id, const INode& inode) -> Result; - auto read_inode(u16 inode_id) -> Result; - auto allocate_inode() -> Result; + void add_inode_to_dir( + INode& dir, const INode& inode, std::string_view name); + auto make_dir_with_inode_ids(u16 inode_id, u16 parent_inode_id) -> INode; + auto write_dir_entry(INode& dir_inode, const DirEntry& entry) -> void; + auto inode_allocate_block(INode& inode) -> u16; + auto inode_last_block(INode& inode) -> u16; - auto allocate_block() -> Result; + auto write_inode(const INode& inode) -> void; + auto read_inode(u16 inode_id) -> INode; + + auto allocate_inode() -> u16; + auto allocate_block() -> u16; void deallocate_block(u16 block_id); - auto sync_from_disk() -> Result; - auto sync_to_disk() -> Result; + auto sync_to_disk() -> void; // templates declared here to get private access template requires(sizeof(Data) <= block_size) - auto read_block_part(u16 block_id, u16 offset, u16 size = sizeof(Data)) - -> Result; + auto write_block(u16 block_id, const Data& data, size_t offset = 0) -> void; template requires(sizeof(Data) <= block_size) - auto write_block_part( - u16 block_id, const Data& data, u16 offset, u16 size = sizeof(Data)) - -> Result; + auto read_block(u16 block_id, size_t offset = 0) -> Data; - template - requires(sizeof(Data) <= block_size) - auto read_block(u16 block_id) -> Result; - template - requires(sizeof(Data) <= block_size) - auto write_block(const Data& data, u16 block_id) -> Result; + void write_block_raw( + u16 block_id, const void* data, size_t size, size_t offset = 0); + void read_block_raw( + void* data, size_t size, u16 block_id, size_t offset = 0); BlockDevice* m_disk; Superblock m_superblock = {}; BlocksBitmap m_blocks_bitmap = {}; + + bool m_out_of_sync = false; }; } diff --git a/src/vm_main.cpp b/src/vm_main.cpp index d89c958..d11b2c3 100644 --- a/src/vm_main.cpp +++ b/src/vm_main.cpp @@ -18,11 +18,11 @@ using namespace vc5; int main(int argc, char** argv) { - auto device = IoDevice::create().value(); - device->set_title("vc5"); + // auto device = IoDevice::create().value(); + // device->set_title("vc5"); if (argc > 2) { - std::println("error: no boot disk (file name) specified"); + std::println("error: no boot disk (filename) specified"); return EXIT_FAILURE; } @@ -37,19 +37,22 @@ int main(int argc, char** argv) } try { - auto fs = filesys::Fs::init_new(disk, 0, 128).value(); + auto fs = filesys::Fs(disk); + fs.init(0, 128); - auto root = fs.root_inode_id().value(); + auto root = fs.root_inode(); auto file = fs.make_file(root, "test"); - } catch (std::bad_expected_access& ex) { - std::println(stderr, "error: {}", ex.error()); + } catch (filesys::FsError& ex) { + std::println(stderr, "error: {}", ex.what()); return EXIT_FAILURE; } - auto vm = VM(*device, disk); - vm.run(); + // auto vm = VM(*device, disk); + // vm.run(); + + std::println("OK!"); } extern "C" const char* __asan_default_options(void)