create files
This commit is contained in:
parent
bb38807ed1
commit
42f24e0e78
@ -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
|
||||
|
||||
168
src/fs.cpp
168
src/fs.cpp
@ -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);
|
||||
|
||||
34
src/fs.hpp
34
src/fs.hpp
@ -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>
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user