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