create files

This commit is contained in:
sfja 2026-02-02 22:34:33 +01:00
parent bb38807ed1
commit 42f24e0e78
4 changed files with 158 additions and 82 deletions

View File

@ -48,24 +48,24 @@ _start:
mov r0, 0 mov r0, 0
mov [counter], r0 mov [counter], r0
mov r1, 0 ; mov r1, 0
.loop_body: ;.loop_body:
mov r2, r1 ; mov r2, r1
add r2, 32 ; add r2, 32
;
add rsp, 4 ; add rsp, 4
mov [rsp-4], r1 ; mov [rsp-4], r1
mov [rsp-2], r2 ; mov [rsp-2], r2
call term_putc ; call term_putc
mov r1, [rsp-4] ; mov r1, [rsp-4]
sub rsp, 4 ; sub rsp, 4
;
add r1, 1 ; add r1, 1
.loop_cond: ;.loop_cond:
cmp r1, 127 - 32 ; cmp r1, 127 - 32
mov r0, rfl ; mov r0, rfl
and r0, fl_lt ; and r0, fl_lt
jnz r0, .loop_body ; jnz r0, .loop_body
main_loop: main_loop:
hlt hlt

View File

@ -62,25 +62,50 @@ auto Fs::init_new(u16 volume_id, u16 block_count) -> Result<void>
return {}; return {};
} }
auto Fs::make_file(u16 dir_inode_id, std::string_view name) -> Result<u16> auto Fs::init_from_existing() -> Result<void>
{
return sync_from_disk();
}
auto Fs::make_file(u16 parent_inode_id, std::string_view name) -> Result<u16>
{
return make_inode(parent_inode_id, name, INodeType::Dir);
}
auto Fs::make_directory(u16 parent_inode_id, std::string_view name)
-> Result<u16>
{
return make_inode(parent_inode_id, name, INodeType::Dir);
}
auto Fs::write(u16 inode_id, const void* data, u16 size) -> Result<u16>
{
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<u16>
{ {
if (name.size() > name_max_len) if (name.size() > name_max_len)
return std::unexpected("invalid filename"); return std::unexpected("invalid filename");
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");
auto inode_id = allocate_inode(); auto inode_id = allocate_inode();
if (not inode_id) if (not inode_id)
return inode_id; return inode_id;
auto inode = INode { auto inode = INode {
.mode = inode_mode(INodeType::File), .mode = inode_mode(type),
.blocks_count = 0, .blocks_count = 0,
.links_count = 0, .links_count = 0,
.last_block_size = 0, .last_block_size = 0,
@ -97,27 +122,45 @@ auto Fs::make_file(u16 dir_inode_id, std::string_view name) -> Result<u16>
std::memcpy(entry.name.data(), name.data(), name.size()); std::memcpy(entry.name.data(), name.data(), name.size());
if (auto result = append_to_directory(dir_inode, entry); not result) if (auto result = append_to_directory(parent_inode_id, entry); not result)
return std::unexpected(result.error()); return std::unexpected(result.error());
if (auto result = write_inode(*inode_id, inode); not result)
return std::unexpected(result.error());
return inode_id;
} }
auto Fs::init_from_existing() -> Result<void> auto Fs::append_to_directory(u16 dir_inode_id, const DirEntry& entry)
{
return sync_from_disk();
}
auto Fs::append_to_directory(INode& dir_inode, const DirEntry& entry)
-> Result<void> -> Result<void>
{ {
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;
for (u16 i = 0; i < inode_ndir_blocks; ++i) { if (inode_mode_type(dir_inode.mode) != INodeType::Dir)
auto dir_entry_block = dir_inode.blocks[i]; return std::unexpected("incorrect inode type");
auto block = read_block<IntBlock<u16>>(dir_entry_block); if (dir_inode.blocks_count == inode_last_block
if (not block) && entry.size() > block_size - dir_inode.last_block_size) {
return std::unexpected(block.error()); 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 {}; return {};
} }
@ -159,29 +202,27 @@ auto Fs::inode_last_block_id(const INode& inode) -> Result<u16>
return ind_block->data[inode.blocks_count - inode_ind_block]; return ind_block->data[inode.blocks_count - inode_ind_block];
} else if (inode.blocks_count == inode_dind_block) {
u16 first_id = inode_dind_block;
u16 second_id = inode.blocks_count - inode_dind_block;
auto first_block_id = inode.blocks[inode_dind_block];
assert(first_block_id != 0);
auto first_ind_block = read_block<IntBlock<u16>>(first_block_id);
if (not first_ind_block)
return std::unexpected(first_ind_block.error());
auto second_block_id
= first_ind_block->data[inode.blocks_count - inode_dind_block];
auto second_ind_block = read_block<IntBlock<u16>>(second_block_id);
if (not second_ind_block)
return std::unexpected(second_ind_block.error());
return second_ind_block->data[inode.blocks_count - inode_dind_block];
} else { } else {
return std::unexpected("inode at capacity"); return std::unexpected("invalid inode");
}
}
template <typename Func>
auto Fs::inode_for_each_block_id(const INode& inode, Func func) -> Result<void>
{
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<IntBlock<u16>>(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]);
} }
} }
@ -269,6 +310,11 @@ auto Fs::allocate_block() -> Result<u16>
return block_id; return block_id;
} }
void Fs::deallocate_block(u16 block_id)
{
m_blocks_bitmap.bitmap[block_id] = false;
}
auto Fs::sync_from_disk() -> Result<void> auto Fs::sync_from_disk() -> Result<void>
{ {
auto superblock = read_block<Superblock>(sb_loc); auto superblock = read_block<Superblock>(sb_loc);
@ -352,7 +398,7 @@ public:
{ {
v = 0; v = 0;
for (std::size_t i = 0; i < sizeof(Int); ++i) { for (std::size_t i = 0; i < sizeof(Int); ++i) {
v |= *m_data << (sizeof(Int) - i - 1) * 8; v |= *m_data << (sizeof(Int) - i - 1) * 8 & 0xff;
m_data++; m_data++;
} }
return *this; return *this;
@ -388,32 +434,40 @@ using BlockData = std::array<u8, block_size>;
template <typename Data> template <typename Data>
requires(sizeof(Data) <= block_size) requires(sizeof(Data) <= block_size)
auto Fs::read_block_part(u16 block_id, u16 offset) -> Result<Data> auto Fs::read_block_part(u16 block_id, u16 offset, u16 size) -> Result<Data>
{ {
assert(sizeof(Data) + offset <= block_size); assert(size + offset <= block_size);
BlockData block = {}; auto block = BlockData {};
m_disk->read(block.data(), block_id); m_disk->read(block.data(), block_id);
auto raw_data = BlockData {};
std::memcpy(raw_data.data(), block.data() + offset, size);
auto reader = BeReader(raw_data.data());
Data data; Data data;
std::memcpy( data.read(reader);
reinterpret_cast<uint8_t*>(&data) + offset, block.data(), sizeof(Data));
return data; return data;
} }
template <typename Data> template <typename Data>
requires(sizeof(Data) <= block_size) requires(sizeof(Data) <= block_size)
auto Fs::write_block_part(u16 block_id, const Data& data, u16 offset) auto Fs::write_block_part(u16 block_id, const Data& data, u16 offset, u16 size)
-> Result<void> -> Result<void>
{ {
assert(sizeof(Data) + offset <= block_size); assert(size + offset <= block_size);
BlockData block = {}; auto raw_data = BlockData {};
auto writer = BeWriter(raw_data.data());
data.write(writer);
auto block = BlockData {};
m_disk->read(block.data(), block_id); m_disk->read(block.data(), block_id);
auto writer = BeWriter(block.data() + offset); std::memcpy(block.data() + offset, raw_data.data(), size);
data.write(writer);
m_disk->write(block.data(), block_id); m_disk->write(block.data(), block_id);
@ -424,7 +478,7 @@ template <typename Data>
requires(sizeof(Data) <= block_size) requires(sizeof(Data) <= block_size)
auto Fs::read_block(u16 block_id) -> Result<Data> auto Fs::read_block(u16 block_id) -> Result<Data>
{ {
BlockData block = {}; auto block = BlockData {};
m_disk->read(block.data(), block_id); m_disk->read(block.data(), block_id);
auto reader = BeReader(block.data()); auto reader = BeReader(block.data());
@ -439,7 +493,7 @@ template <typename Data>
requires(sizeof(Data) <= block_size) requires(sizeof(Data) <= block_size)
auto Fs::write_block(const Data& data, u16 block_id) -> Result<void> auto Fs::write_block(const Data& data, u16 block_id) -> Result<void>
{ {
BlockData block = {}; auto block = BlockData {};
auto writer = BeWriter(block.data()); auto writer = BeWriter(block.data());
data.write(writer); data.write(writer);

View File

@ -31,6 +31,12 @@ struct DirEntry {
{ {
r >> inode >> next >> name_len >> name; 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 inode_size = 32;
@ -45,10 +51,11 @@ enum class INodeType : u16 {
constexpr u16 inode_type_bitoffset = 0; constexpr u16 inode_type_bitoffset = 0;
constexpr u16 inode_type_bitmask = 0b11; constexpr u16 inode_type_bitmask = 0b11;
constexpr u16 inode_ndir_blocks = 8; constexpr u16 inode_ndir_blocks = 9;
constexpr u16 inode_ind_block = inode_ndir_blocks; constexpr u16 inode_ind_block = inode_ndir_blocks;
constexpr u16 inode_dind_block = inode_ind_block + 1; constexpr u16 inode_blocks_count = inode_ind_block + 1;
constexpr u16 inode_blocks_count = inode_dind_block + 1;
constexpr u16 inode_last_block = inode_ndir_blocks + block_size;
struct INode { struct INode {
u16 mode; u16 mode;
@ -167,23 +174,34 @@ public:
return m_superblock.root_inode; return m_superblock.root_inode;
} }
auto make_file(u16 dir_inode_id, std::string_view name) -> Result<u16>; auto make_file(u16 parent_inode_id, std::string_view name) -> Result<u16>;
auto make_directory(u16 parent_inode_id, std::string_view name)
-> Result<u16>;
auto write(u16 inode_id, const void* data, u16 size) -> Result<u16>;
private: private:
auto init_new(u16 volume_id, u16 block_count) -> Result<void>; auto init_new(u16 volume_id, u16 block_count) -> Result<void>;
auto init_from_existing() -> Result<void>; auto init_from_existing() -> Result<void>;
auto append_to_directory(INode& dir_inode, const DirEntry& entry) auto make_inode(u16 parent_inode_id, std::string_view name, INodeType type)
-> Result<u16>;
auto append_to_directory(u16 dir_inode_id, const DirEntry& entry)
-> Result<void>; -> Result<void>;
auto make_directory_inode() -> Result<u16>; auto make_directory_inode() -> Result<u16>;
auto inode_last_block_id(const INode& inode) -> Result<u16>; auto inode_last_block_id(const INode& inode) -> Result<u16>;
template <typename Func>
auto inode_for_each_block_id(const INode& inode, Func func) -> Result<void>;
auto write_inode(u16 inode_id, const INode& inode) -> Result<void>; auto write_inode(u16 inode_id, const INode& inode) -> Result<void>;
auto read_inode(u16 inode_id) -> Result<INode>; auto read_inode(u16 inode_id) -> Result<INode>;
auto allocate_inode() -> Result<u16>; auto allocate_inode() -> Result<u16>;
auto allocate_block() -> Result<u16>; auto allocate_block() -> Result<u16>;
void deallocate_block(u16 block_id);
auto sync_from_disk() -> Result<void>; auto sync_from_disk() -> Result<void>;
auto sync_to_disk() -> Result<void>; auto sync_to_disk() -> Result<void>;
@ -192,10 +210,12 @@ private:
template <typename Data> template <typename Data>
requires(sizeof(Data) <= block_size) requires(sizeof(Data) <= block_size)
auto read_block_part(u16 block_id, u16 offset) -> Result<Data>; auto read_block_part(u16 block_id, u16 offset, u16 size = sizeof(Data))
-> Result<Data>;
template <typename Data> template <typename Data>
requires(sizeof(Data) <= block_size) requires(sizeof(Data) <= block_size)
auto write_block_part(u16 block_id, const Data& data, u16 offset) auto write_block_part(
u16 block_id, const Data& data, u16 offset, u16 size = sizeof(Data))
-> Result<void>; -> Result<void>;
template <typename Data> template <typename Data>

View File

@ -41,6 +41,8 @@ int main(int argc, char** argv)
auto root = fs.root_inode_id().value(); auto root = fs.root_inode_id().value();
auto file = fs.make_file(root, "test");
} catch (std::bad_expected_access<std::string_view>& ex) { } catch (std::bad_expected_access<std::string_view>& ex) {
std::println(stderr, "error: {}", ex.error()); std::println(stderr, "error: {}", ex.error());
return EXIT_FAILURE; return EXIT_FAILURE;