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 [counter], r0
mov r1, 0
.loop_body:
mov r2, r1
add r2, 32
add rsp, 4
mov [rsp-4], r1
mov [rsp-2], r2
call term_putc
mov r1, [rsp-4]
sub rsp, 4
add r1, 1
.loop_cond:
cmp r1, 127 - 32
mov r0, rfl
and r0, fl_lt
jnz r0, .loop_body
; mov r1, 0
;.loop_body:
; mov r2, r1
; add r2, 32
;
; add rsp, 4
; mov [rsp-4], r1
; mov [rsp-2], r2
; call term_putc
; mov r1, [rsp-4]
; sub rsp, 4
;
; add r1, 1
;.loop_cond:
; cmp r1, 127 - 32
; mov r0, rfl
; and r0, fl_lt
; jnz r0, .loop_body
main_loop:
hlt

View File

@ -62,25 +62,50 @@ auto Fs::init_new(u16 volume_id, u16 block_count) -> Result<void>
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)
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();
if (not inode_id)
return inode_id;
auto inode = INode {
.mode = inode_mode(INodeType::File),
.mode = inode_mode(type),
.blocks_count = 0,
.links_count = 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());
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());
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>
{
return sync_from_disk();
}
auto Fs::append_to_directory(INode& dir_inode, const DirEntry& entry)
auto Fs::append_to_directory(u16 dir_inode_id, const DirEntry& entry)
-> 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) {
auto dir_entry_block = dir_inode.blocks[i];
if (inode_mode_type(dir_inode.mode) != INodeType::Dir)
return std::unexpected("incorrect inode type");
auto block = read_block<IntBlock<u16>>(dir_entry_block);
if (not block)
return std::unexpected(block.error());
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 {};
}
@ -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];
} 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 {
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;
}
void Fs::deallocate_block(u16 block_id)
{
m_blocks_bitmap.bitmap[block_id] = false;
}
auto Fs::sync_from_disk() -> Result<void>
{
auto superblock = read_block<Superblock>(sb_loc);
@ -352,7 +398,7 @@ public:
{
v = 0;
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++;
}
return *this;
@ -388,32 +434,40 @@ using BlockData = std::array<u8, block_size>;
template <typename Data>
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);
auto raw_data = BlockData {};
std::memcpy(raw_data.data(), block.data() + offset, size);
auto reader = BeReader(raw_data.data());
Data data;
std::memcpy(
reinterpret_cast<uint8_t*>(&data) + offset, block.data(), sizeof(Data));
data.read(reader);
return data;
}
template <typename Data>
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>
{
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);
auto writer = BeWriter(block.data() + offset);
data.write(writer);
std::memcpy(block.data() + offset, raw_data.data(), size);
m_disk->write(block.data(), block_id);
@ -424,7 +478,7 @@ template <typename Data>
requires(sizeof(Data) <= block_size)
auto Fs::read_block(u16 block_id) -> Result<Data>
{
BlockData block = {};
auto block = BlockData {};
m_disk->read(block.data(), block_id);
auto reader = BeReader(block.data());
@ -439,7 +493,7 @@ template <typename Data>
requires(sizeof(Data) <= block_size)
auto Fs::write_block(const Data& data, u16 block_id) -> Result<void>
{
BlockData block = {};
auto block = BlockData {};
auto writer = BeWriter(block.data());
data.write(writer);

View File

@ -31,6 +31,12 @@ struct DirEntry {
{
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;
@ -45,10 +51,11 @@ enum class INodeType : u16 {
constexpr u16 inode_type_bitoffset = 0;
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_dind_block = inode_ind_block + 1;
constexpr u16 inode_blocks_count = inode_dind_block + 1;
constexpr u16 inode_blocks_count = inode_ind_block + 1;
constexpr u16 inode_last_block = inode_ndir_blocks + block_size;
struct INode {
u16 mode;
@ -167,23 +174,34 @@ public:
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:
auto init_new(u16 volume_id, u16 block_count) -> 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>;
auto make_directory_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 read_inode(u16 inode_id) -> Result<INode>;
auto allocate_inode() -> Result<u16>;
auto allocate_block() -> Result<u16>;
void deallocate_block(u16 block_id);
auto sync_from_disk() -> Result<void>;
auto sync_to_disk() -> Result<void>;
@ -192,10 +210,12 @@ private:
template <typename Data>
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>
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>;
template <typename Data>

View File

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